为什么 vc++ 2019 不接受代码?
Why does the vc++ 2019 not accept the code?
template<int N>
void f()
{
constexpr int n = 9;
++*const_cast<int*>(&n); // ok
++*const_cast<int*>(&N); // error C2101: '&' on constant
}
int main()
{
f<8>();
}
根据cppref:
the name of a variable, a function, a template parameter object (since
C++20), or a data member, regardless of type, such as std::cin or
std::endl. Even if the variable's type is rvalue reference, the
expression consisting of its name is an lvalue expression;
两个问题:
1.为什么 vc++ 2019 (with /std:c++latest) 不接受代码?
2。为什么 C++20 允许模板参数对象是左值?
模板参数在编译时被相应的值替换。所以 N 不是变量,更像是一个宏。在您的示例中,您调用 f<8>() 因此行 ++*const_cast<int*>(&N);
将变为 ++*const_cast<int*>(&8);
当然你不能取8的地址。
模板参数对象是一个规范术语,仅指具有class类型的模板参数。
temp.param/6 (emphasis mine)
...An id-expression naming a non-type template-parameter of class type T
denotes a static storage duration object of type const T, known as a
template parameter object, whose value is that of the corresponding
template argument after it has been converted to the type of the
template-parameter. All such template parameters in the program of the
same type with the same value denote the same template parameter
object. [ Note: If an id-expression names a non-type non-reference
template-parameter, then it is a prvalue if it has non-class type.
Otherwise, if it is of class type T, it is an lvalue and has type
const T ([expr.prim.id.unqual]). — end note ]
因为 int
不是 class 类型,所以 它不是 模板参数对象。关于取值类别的规范性文本可以参考相关章节,支持注解:
... The expression is an lvalue if the entity is a function, variable,
structured binding ([dcl.struct.bind]), data member, or template
parameter object and a prvalue otherwise ...
由于我们不在 "template parameter object" 的情况下,我们正在处理纯右值,因此可能不会像任何其他纯右值一样将一元 &
应用于它。
template<int N>
void f()
{
constexpr int n = 9;
++*const_cast<int*>(&n); // ok
++*const_cast<int*>(&N); // error C2101: '&' on constant
}
int main()
{
f<8>();
}
根据cppref:
the name of a variable, a function, a template parameter object (since C++20), or a data member, regardless of type, such as std::cin or std::endl. Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression;
两个问题:
1.为什么 vc++ 2019 (with /std:c++latest) 不接受代码?
2。为什么 C++20 允许模板参数对象是左值?
模板参数在编译时被相应的值替换。所以 N 不是变量,更像是一个宏。在您的示例中,您调用 f<8>() 因此行 ++*const_cast<int*>(&N);
将变为 ++*const_cast<int*>(&8);
当然你不能取8的地址。
模板参数对象是一个规范术语,仅指具有class类型的模板参数。
temp.param/6 (emphasis mine)
...An id-expression naming a non-type template-parameter of class type T denotes a static storage duration object of type const T, known as a template parameter object, whose value is that of the corresponding template argument after it has been converted to the type of the template-parameter. All such template parameters in the program of the same type with the same value denote the same template parameter object. [ Note: If an id-expression names a non-type non-reference template-parameter, then it is a prvalue if it has non-class type. Otherwise, if it is of class type T, it is an lvalue and has type const T ([expr.prim.id.unqual]). — end note ]
因为 int
不是 class 类型,所以 它不是 模板参数对象。关于取值类别的规范性文本可以参考相关章节,支持注解:
... The expression is an lvalue if the entity is a function, variable, structured binding ([dcl.struct.bind]), data member, or template parameter object and a prvalue otherwise ...
由于我们不在 "template parameter object" 的情况下,我们正在处理纯右值,因此可能不会像任何其他纯右值一样将一元 &
应用于它。