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