Search code examples
c++standardsc++20c++-conceptstypename

Why is `typename` prefix still required in such a case in C++20?


According to https://stackoverflow.com/a/61991146/508343:

One of the new features in C++20 is Down with typename.

In C++17, you had to provide the typename keyword in nearly all† dependent contexts to disambiguate a type from a value. But in C++20, this rule is relaxed a lot. In all contexts where you need to have a type, the typename keyword is no longer mandatory.

template<typename T>
concept IsOK = true;

template<typename T>
requires IsOK<T::U> // error: use ‘typename T::U’
void f()
{}

struct A
{
    using U = int;
};

int main()
{
    f<A>(); 
}

In the code above, obviously, IsOK concept can take types only.

Why is typename required here?

See online demo


Solution

  • The answer is speaking loosely about what "context" means. What the feature is doing is finding places where it is grammatically impossible for anything other than a typename to appear in that location. It is those places where typename is no longer necessary.

    For example, using name = X;. Grammatically, this is a type alias declaration. As such, whatever X is, the grammar requires that it be a type. If the X happens to be a name dependent on a template parameter, whatever that name is must be a type. So the grammar is unambiguous, and typename is redundant.

    The syntax name<X> states that X is a template argument to the template name. But template arguments do not have to be types. A specific template may take a type as a specific argument, but grammatically, X could be an identifier referencing a variable or a template. Therefore, you must disambiguate ambiguous dependent Xs.