Ant*_*ier 9 c++ language-lawyer constexpr c++11
这段代码用clang和gcc编译得很好.
template<size_t n>
struct N {
static constexpr size_t v = n;
};
template<size_t n>
constexpr bool operator<(N<n>, size_t n2) {
return n < n2;
}
template<typename N>
constexpr void foo(N v) {
static_assert(v < 5);
}
int main()
{
foo(N<3>{});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用MSVC,我得到的错误v < 5不是常量表达式.我能理解为什么MSVC会这么想,但我认为这是错误的,而clang/gcc是对的.这是来自MSVC的错误吗?
是的,MSVC在这里是错误的.
代码结构良好似乎是违反直觉的,因为如何(可能v不是常量表达式)可能在常量表达式中使用?
那么为什么允许呢?首先,非正式地考虑,如果表达式求值为glvalue本身不是常量表达式,或者是一个在封闭表达式之外开始生命的变量([expr.const] p2.7),则表达式不是常量表达式.
第二,operator<是constexpr.
现在,会发生什么是v < 5有效的常量表达式.要理解这一点,我们来看看表达式的评估.
我们有:
v < 5 打电话给你 constexpr operator<n2在评估中开始了它的生命v < 5并且是文字的n 是一个非类型模板参数,因此可用于常量表达式n < n2调用内置运算符.所有这些都没有违反[expr.const] p2中的任何一点,因此生成的表达式实际上是一个用作参数的常量表达式static_assert.
这些类型的表达式称为转换常量表达式.
这是一个简化的例子:
struct Foo {
constexpr operator bool() { return true; }
};
int main() {
Foo f;
static_assert(f);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
329 次 |
| 最近记录: |