简体   繁体   中英

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>();
}

According to 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;

Two questions:

1. Why does vc++ 2019 (with /std:c++latest) not accept the code?

2. Why does C++20 permit a template parameter object be an lvalue?

template parameter object is a normative term, that refers only to template parameters that have a class type.

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 ]

Since int is not of a class type, it's not a template parameter object. We can consult the relevant section for the normative text on the value category here, which supports the note:

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 ...

Since we are not in the "template parameter object" case, we are dealing with a prvalue, and as such may not apply unary & to it, like any other prvalue.

Template parameters get replaced by the corresponding values at compile time. So N is no variable, but more like a macro. In you example you call f<8>() so the line ++*const_cast<int*>(&N); will become ++*const_cast<int*>(&8);

And of course you can't take the address of 8.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM