败犬日报 2026-01-12
败犬日报 2026-01-12
1. 编译期检查类的一些字段非空
一般来说可以用构造函数传递所有字段,从而保证非空。群友给了 builder + 模板的办法,不知道实用性如何(代码量大,建议在代码生成时使用):
cpp
#include <iostream>
struct A {
int x;
std::string y;
};
template <bool is_set_x = false, bool is_set_y = false, bool is_set_z = false>
struct A_Builder {
static A_Builder<false, false, false> create() {
return A_Builder<false, false, false>();
}
A_Builder<true, is_set_y, is_set_z> set_x(int x) {
A_Builder<true, is_set_y, is_set_z> rhs;
rhs.a_ = a_;
rhs.a_.x = x;
return rhs;
}
A_Builder<is_set_x, true, is_set_z> set_y(const std::string& y) {
A_Builder<is_set_x, true, is_set_z> rhs;
rhs.a_ = a_;
rhs.a_.y = y;
return rhs;
}
A build() {
static_assert(is_set_x, "Field x is not set");
static_assert(is_set_y, "Field y is not set");
return a_;
}
private:
template <bool Sx, bool Sy, bool Sz>
friend struct A_Builder;
A a_;
};
int main() {
A a = A_Builder<>::create().set_x(42).set_y("Hello").build();
std::cout << "A.x: " << a.x << ", A.y: " << a.y << std::endl;
}也可以实现 required<T>,然后用聚合初始化:
cpp
#include <iostream>
template <typename T>
struct required {
T data;
template <typename U>
required(U&& data) : data(data) {}
};
struct A {
int x;
std::string y;
};
struct A_Builder {
required<int> x;
required<std::string> y;
A build() { return A{std::move(x.data), std::move(y.data)}; }
};
int main() {
A a = A_Builder{.x = 42, .y = "Hello"}.build();
std::cout << "A.x: " << a.x << ", A.y: " << a.y << std::endl;
return 0;
}