非 constexpr 变量有时可用于 constexpr 上下文?
Non-constexpr variable sometimes usable in a constexpr context?
看看下面的代码示例:
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 然后会产生这些错误消息:
error: non-constant condition for static assertion
error: the value of ‘t’ is not usable in a constant expression
note: ‘t’ was not declared ‘constexpr’
这对我来说非常有意义,也正是我所想的。但我真的不知道为什么其他两个静态断言首先编译。允许这样做的标准中的相关段落是什么?
具体来说,这是如何形式化的?仅使用变量与实际访问其运行时值(这将是 constexpr 上下文中唯一被禁止的事情)之间是否存在明确定义的区别?
这只是规则。在 constexpr
之前,const
用常量表达式初始化的变量本身可以用作常量表达式(也为了与 C 的某些兼容性)
从标准[expr.const]/3
:
A variable is usable in constant expressions after its initializing declaration is encountered if [...] it is a constant-initialized variable [...] of const-qualified integral or enumeration type.
这不会扩展到 const auto t = test<true>{}
,因为 test<true>
不是整数类型(您需要 constexpr auto t = test<true>{}
,正如预期的那样,遵循其余部分的规则款)
无法在编译时计算 value_b
的地址。
只能将静态数据成员声明为constexpr
。
相关:Why can't non-static data members be constexpr?
In particular, how is this formalized?
http://eel.is/c++draft/expr.const#4.1
An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following:
this
([expr.prim.this]), except in a constexpr function ([dcl.constexpr]) that is being evaluated as part of e;
访问非静态成员计算 this
指针。访问静态成员不会。
看看下面的代码示例:
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 然后会产生这些错误消息:
error: non-constant condition for static assertion
error: the value of ‘t’ is not usable in a constant expression
note: ‘t’ was not declared ‘constexpr’
这对我来说非常有意义,也正是我所想的。但我真的不知道为什么其他两个静态断言首先编译。允许这样做的标准中的相关段落是什么?
具体来说,这是如何形式化的?仅使用变量与实际访问其运行时值(这将是 constexpr 上下文中唯一被禁止的事情)之间是否存在明确定义的区别?
这只是规则。在 constexpr
之前,const
用常量表达式初始化的变量本身可以用作常量表达式(也为了与 C 的某些兼容性)
从标准[expr.const]/3
:
A variable is usable in constant expressions after its initializing declaration is encountered if [...] it is a constant-initialized variable [...] of const-qualified integral or enumeration type.
这不会扩展到 const auto t = test<true>{}
,因为 test<true>
不是整数类型(您需要 constexpr auto t = test<true>{}
,正如预期的那样,遵循其余部分的规则款)
无法在编译时计算 value_b
的地址。
只能将静态数据成员声明为constexpr
。
相关:Why can't non-static data members be constexpr?
In particular, how is this formalized?
http://eel.is/c++draft/expr.const#4.1
An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine ([intro.execution]), would evaluate one of the following:
this
([expr.prim.this]), except in a constexpr function ([dcl.constexpr]) that is being evaluated as part of e;
访问非静态成员计算 this
指针。访问静态成员不会。