42

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?

Community
  • 1
  • 1
vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • 3
    For the downvoters: I don't ask questions for the sake of getting some points. In case you think the question is crap, or the answer is trivial, at least let me know. I'd very much like to see modern C++ simplified, and getting a cleaner syntax is (imo) worthwhile. – vsoftco Jan 25 '17 at 00:52
  • This is one of the "nobody ever proposed it" cases. I can't think of a technical argument against it. – Columbo Jan 25 '17 at 00:54
  • @Columbo That's why I asked the question, it's a follow up to a comment by Brian for [his answer](http://stackoverflow.com/a/41841216/3093378) to [this question](http://stackoverflow.com/q/41841195/3093378). – vsoftco Jan 25 '17 at 00:55
  • BTW what makes you think it's not optional there? The answer you refer to was adding a missing `typedef`, not `typename`. – Ben Voigt Jan 25 '17 at 01:25
  • @BenVoigt I've posted links to gcc and clang choking on the example – vsoftco Jan 25 '17 at 01:27
  • 2
    Thanks that's pretty convincing. – Ben Voigt Jan 25 '17 at 01:29
  • Closely related (although the reasoning there doesn't apply here): http://stackoverflow.com/q/21625119/103167 – Ben Voigt Jan 25 '17 at 01:31
  • 1
    @BenVoigt Funny thing, VC++ accepts the code, http://rextester.com/HYWJH30088. But (as mentioned in the updated edit), I don't really trust VC++ as a fully standard compliant complier. Thanks for the example, yes it has the same flavour, but with `typedef` things can get a bit harder to parse. However with a `using`, even myself can write a parser pretty fast. – vsoftco Jan 25 '17 at 01:34
  • Yeah, `typename` is known to be one of the big non-conformances in MSVC. – Ben Voigt Jan 25 '17 at 01:34
  • 11
    One of the rationales floated on std-discussion? last time it came up is that it blocks potential evolution paths (e.g., using `using` to declare expression aliases). – T.C. Jan 25 '17 at 05:08
  • 1
    @T.C. Can you post a link or perhaps write an answer? How can it mess up with expr. aliases? I'll probably attend the committee meeting in Toronto this summer and may raise this issue (although it's a pretty small one), so I'd like to know first if it makes some sense raising it. – vsoftco Feb 25 '17 at 23:10
  • If you assume that the rhs of a *using-declaration* is always a type, then you can't have `using tvalue = T::value;` to mean that `tvalue` is an alias for the expression `T::value`. – T.C. Feb 25 '17 at 23:45
  • @T.C. Thanks, got it now, you meant "potential evolution paths", i.e. things that are not yet implemented yet... Ok, frankly I don't know how those things will end up being more useful rather than bloating the language, probably will need to read one of the papers. – vsoftco Feb 26 '17 at 00:02
  • 4
    There has been a proposal ([p0634r0](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0634r0.pdf)) for this, though I'm not sure what its current status is. – ralismark Apr 19 '17 at 09:35
  • 1
    Does `typename` help disambiguate `using type T = decltype(...)`, perhaps? Saves the compiler going looking for a type member named `decltype`. – TBBle Apr 30 '17 at 15:03
  • @ralismark [p0634r0](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0634r0.pdf) was in the "post-Kona" mailing, so it probably came out of discussions at the Kona meeting, and there hasn't been a committee meeting since. It's marked for the Evolution Working Group, who (according to a [trip report](https://botondballo.wordpress.com/2017/03/27/trip-report-c-standards-meeting-in-kona-february-2017/)) sound like they had larger fish to fry, such as Modules, Reflection, and final C++17 things. So stay tuned, C++17's done so hopefully some of these smaller things will start moving along. – TBBle May 10 '17 at 23:53

2 Answers2

3

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.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76
0

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.

Michaël Roy
  • 6,338
  • 1
  • 15
  • 19
  • I remember that item 9 of modern c++ have your question as a reason to choose using instead of typedef. Maybe this time vc is more compianto than clang ? – alangab Jun 27 '17 at 19:26
  • 1
    The point was that you *already* told the compiler that `T::type` is a type, because you cannot put a non-type on the RHS of a `using` declaration. Why do you need to tell it *again* with `typename`? In other places it’s necessary for disambiguation, but not here. – Daniel H Jul 26 '17 at 18:44
  • You *can* put a non-type there and it will issue a diagnostic. It will make the language irregular if they change this and that can have many unintended consequences that results in closing the avenues for evolution. Currently `T::a` (for class template `T`) is always a value unless preceded by `typename`, and `using` always reports an error when used with a value. This is a regular rule and so it's easy to explain, implement, and to plan language evolution. – codeshot Aug 30 '17 at 19:33