看看下面的代码示例:
template<bool val>
struct test {
static const int value_a = val;
const int value_b = val;
constexpr int get_value_a() const noexcept { return value_a; }
constexpr int get_value_b() const noexcept { return value_b; }
};
int main(int argc, char** argv) {
auto t = test<true>{};
static_assert(t.value_a);
// static_assert(t.value_b);
static_assert(t.get_value_a());
// static_assert(t.get_value_b());
}
gcc和clang都同意应对此进行编译,但是包括任何已注释掉的静态断言会使它无效。例如,gcc然后会产生以下错误消息:
错误:静态声明的非恒定条件
错误:常量表达式不能使用't'值
注意:“ t”未声明为“ constexpr”
这对我来说非常有意义,而这正是我所想的。但是我真的不知道为什么其他两个静态断言首先要编译。标准中允许该内容的相关段落是什么?
尤其是这是如何形式化的?仅使用变量与实际访问其运行时值(这将是constexpr上下文中唯一被禁止的东西)之间是否有明确定义的区别?
答案 0 :(得分:1)
这只是规则。在constexpr
之前,用常量表达式初始化的const
变量本身可以用作常量表达式(也可以与C兼容)
根据标准[expr.const]/3
:
如果变量是常量限定的整数或枚举类型的常量初始化变量,则遇到初始化声明后,该变量即可在常量表达式中使用。
这不会扩展到const auto t = test<true>{}
,因为test<true>
不是整数类型(按照预期,您需要拥有constexpr auto t = test<true>{}
,遵循该段其余部分的规则)
答案 1 :(得分:1)
尤其是这是如何形式化的?
http://eel.is/c++draft/expr.const#4.1
表达式e是核心常量表达式,除非按照抽象机([intro.execution])的规则对e求值将对以下值之一进行求值:
this
([expr.prim.this]),但作为e的一部分的constexpr函数([dcl.constexpr])除外;
对非静态成员的访问将评估this
指针。不能访问静态成员。
答案 2 :(得分:0)