3

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

xmllmx
  • 39,765
  • 26
  • 162
  • 323
  • I imagine it simplifies the job of compiler writers somehow. – Aykhan Hagverdili Aug 21 '21 at 15:18
  • Template arguments are strange. I know it's not the same as this concept case, but: If the argument could be parsed as either an expression or a type (e.g. `int()`), it is always a type, no matter how the template being used is declared. On the other hand, if the argument is an injected-class-name of a class template, it could mean either the template or the current instantiation type, and the meaning does depend on the declaration of the template being used. – aschepler Aug 21 '21 at 15:25

1 Answers1

13

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.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • but here `IsOK` was already declared as `template`, so definitely in `IsOK` X must be a type, nothing else is possible – phuclv Apr 11 '22 at 16:00
  • @phuclv: That would require the validity of the code to be based on what `IsOK` is. That's my point; the paper only removes the requirement of `typename` when it is *grammatically impossible* for anything other than a typename to appear. It is not the rules of C++ grammar that require `X` in `IsOK` to be a typename; it's the rules of instantiating `IsOK`. Grammar is about the structure of code; semantics like template instantiation are about the *meaning* of code. – Nicol Bolas Apr 11 '22 at 16:13
  • Funny how the code would be invalid if the argument was `int()` and the parameter was `int V` for the opposite reason (`int()` taken as a type). – Johannes Schaub - litb Jan 13 '23 at 15:35