vsoftco
vsoftco

Reputation: 56557

Why does one still need to disambiguate a dependent type with typename in the RHS of a using statement?

I know very well why one needs to use typename for dependent types, since the compiler may not be able to disambiguate between a type and a variable declaration when it sees something like T::type, see e.g. this answer for a great explanation. TL;DR: in an expression like T::type * x;, the compiler cannot "know" whether T::type is a type or perhaps a variable declared in some particular specialization for T.

However, in something like

using type = T::type;

there is nothing ambiguous. IMO, T::type should always be parsed as a type, as it's part of the RHS of a using statement. However, we still need to use the typename here (at least according to gcc and clang),

using type = typename T::type;

Live on Coliru, gcc Live on Coliru, clang

Visual C++ seems to accept the code without a typename, however I don't have too much faith in the compiler being fully standard compliant (in fact, it has many non-standard extensions, e.g. binding rvalues to non-const references).

Question: Is there any reason why this is not an exception to the typename rule in C++11 and later?

Upvotes: 42

Views: 1136

Answers (2)

Davis Herring
Davis Herring

Reputation: 39818

There is no hard reason. As ralismark said, a paper was discussed this year (for C++20, not 17!). There are concerns, but also counterpoints:

  1. It could be seen as making the language less regular (as codeshot said), but the new idea is that disambiguating typename will become rare enough as to have near-consistency in the other direction. (As has been said, there was already an exceptional case in the form of base class names.)
  2. It could foreclose possible extensions (as T.C. reported), but the extensions could have their own disambiguation rather than burdening the common case.

The paper has strong support and the new rules will probably appear in the working draft in a few months.

Upvotes: 3

Michaël Roy
Michaël Roy

Reputation: 6471

The template argument type T does not, and can not implicitly carry with it its internal components. thus T::type is fundamentally a new type when the compiler looks at the uninstantiated template, hence the need to declare a new typename 'T::type'.

Unfortunately, I think this issue will remain with us until the standard includes full-fledged Concepts.

Upvotes: 0

Related Questions