为什么 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 类型,所以 它不是 模板参数对象。关于取值类别的规范性文本可以参考相关章节,支持注解:

expr.prim.id.unqual/2

... 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" 的情况下,我们正在处理纯右值,因此可能不会像任何其他纯右值一样将一元 & 应用于它。