c++ - 为什么 constexpr 成员不能用于 static_assert?

标签 c++ constexpr

此代码被 clang 拒绝,因为 t.n 不是编译时常量。

template<int N>
struct s{
  constexpr static int n = N;
};

template<typename T>
void test(T& t){
  static_assert(t.n == 1);
}

int main(){
  s<1> str;
  test(str);
}

但是 g++ 让这一切过去了。

哪种行为符合标准?

一个更奇怪的事实是,如果我将 test 的参数从 T& t 更改为 T t,这将建立在两者之上。 常量性发生了什么变化?

(恐怕标题可能无法正确或详细地描述这个问题。请随意给我更合适的标题)

最佳答案

我相信(但信心不足)Clang 是正确的,因为根据标准,核心常量表达式可能包含:

an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization and either

— it is initialized with a constant expression or

— it is a non-static data member of an object whose lifetime began within the evaluation of e;

t是引用类型的变量。假设(正如我所做的那样,信心不足)“前面的初始化”意味着在可能的常量表达式发生的点上词法上的初始化,因为参数的初始化发生在调用者的范围内,t不满足这个要求,所以t.n确实不能用在常量表达式中。

如果参数类型更改为 T,则此取消资格的要点不再适用。

(即使您接受我的解释,仍然存在歧义;请参阅 CWG 2186 )

关于c++ - 为什么 constexpr 成员不能用于 static_assert?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41372217/

相关文章:

c++ - OOP - 这应该如何完成?

c++ - 如何返回不可用的 const 引用

C++ - 我可以创建编译时变量对象吗?

c++ - constexpr 构造函数不被称为隐式类型转换的 constexpr

c++ - 默认构造函数 C++

c++ - 在 C++、QT 中创建 setup.exe

c++ - 在编译时初始化 c++ std::bitset

c++ - 是否存在应该避免使用 constexpr 的情况,即使它可以使用?

c++ - 为什么不是来自 std::array 双向/随机访问的 ConstexprIterator?

c++ - 前向声明 : incomplete type 'enums::Category' used in nested name specifier 有问题