在构造函数中使用 constexpr 成员
Using constexpr member in constructor
我有以下代码:
struct C {
int var = 3;
};
当我这样使用它时:
constexpr C c;
static_assert(c.var == 3, "");
一切正常,但是如果我想在 constexpr
构造函数中执行此断言,它会失败:
struct C {
constexpr C() { static_assert(var == 3, ""); }
int var = 3;
};
为什么会这样?
在 constexpr
构造函数中,每个变量都应该在编译时知道,对吗?
In constexpr constructor every variable should be known at compile time, right?
错了。
A constexpr
构造函数是一个函数(方法),可以在编译时执行(在你的情况下,声明 c
constexpr
),但也可以在 运行 时执行(例如,声明 C c2;
而不是 constexpr
)。
所以构造函数里面的static_assert()
是错误的,因为编译器在执行构造函数的时候检查不到运行-time.
也就是说……
当你按如下方式使用时
constexpr C c;
static_assert(c.var == 3, "");
可以编译,因为 c
被声明为 constexpr
,所以 c.var
的值在编译时已知。
但是
C c2;
static_assert(c2.var == 3, "");
给出错误,因为 c2.var
的值不知道编译时间。
写作
constexpr C() { static_assert(var == 3, ""); }
要求在两种情况下都执行 static_assert()
。
constexpr
-函数,无论是构造函数、(静态)成员函数还是自由函数,都是可以在假定适当参数的情况下在编译时求值的函数。
不保证任何特定调用都会在编译时求值,除非它是在需要编译时常量的上下文中完成的。
因此,您不能在需要编译时常量表达式的地方使用任何非 static constexpr
成员。
即使是 GCC 的 __builtin_constant_p()
,它允许您有更多的回旋余地,但出于某种原因却无济于事:
我有以下代码:
struct C {
int var = 3;
};
当我这样使用它时:
constexpr C c;
static_assert(c.var == 3, "");
一切正常,但是如果我想在 constexpr
构造函数中执行此断言,它会失败:
struct C {
constexpr C() { static_assert(var == 3, ""); }
int var = 3;
};
为什么会这样?
在 constexpr
构造函数中,每个变量都应该在编译时知道,对吗?
In constexpr constructor every variable should be known at compile time, right?
错了。
A constexpr
构造函数是一个函数(方法),可以在编译时执行(在你的情况下,声明 c
constexpr
),但也可以在 运行 时执行(例如,声明 C c2;
而不是 constexpr
)。
所以构造函数里面的static_assert()
是错误的,因为编译器在执行构造函数的时候检查不到运行-time.
也就是说…… 当你按如下方式使用时
constexpr C c;
static_assert(c.var == 3, "");
可以编译,因为 c
被声明为 constexpr
,所以 c.var
的值在编译时已知。
但是
C c2;
static_assert(c2.var == 3, "");
给出错误,因为 c2.var
的值不知道编译时间。
写作
constexpr C() { static_assert(var == 3, ""); }
要求在两种情况下都执行 static_assert()
。
constexpr
-函数,无论是构造函数、(静态)成员函数还是自由函数,都是可以在假定适当参数的情况下在编译时求值的函数。
不保证任何特定调用都会在编译时求值,除非它是在需要编译时常量的上下文中完成的。
因此,您不能在需要编译时常量表达式的地方使用任何非 static constexpr
成员。
即使是 GCC 的 __builtin_constant_p()
,它允许您有更多的回旋余地,但出于某种原因却无济于事: