3

I've gotten quite used to the obligatory use of typename in class-templates, but can't help but wonder if if it's really necessary. This question was asked before here on SO, but I wasn't quite satisfied with the answers (and neither was the OP if I understood correctly).

The when and where is perfectly clear (from cppreference.com):

In a declaration or a definition of a template, including alias template, a name that is not a member of the current instantiation and is dependent on a template parameter is not considered to be a type unless the keyword typename is used or unless it was already established as a type name, e.g. with a typedef declaration or by being used to name a base class.

When a (class- or function-)template is defined (not instantiated yet), I understand that the statement

A::Type *tp;

where A is a template type-parameter and Type should be a nested type, is ambiguous. Type might as well be a static member or enum value, or whatever other possibilities there are that I can't think of right now. The * operator in this case is a multiplication (assuming "multiplication" is the correct wording for the implementation of operator*()) rather than a pointer declaration. I can't, however, think of any situation where such a statement could represent a multiplication in class scope. In function-scope, sure, but what could this mean in class-scope other than a pointer declaration?

My point being that in many cases the compiler expects a typename at some point, but still demands from us that we explicitly specify this, even though there are no other options. The fact that GCC and Clang both emit an error rather than a warning is pretty illustrative:

template <typename T>
struct A
{
    T::x *p;
};

GCC:    error: need ‘typename’ before ‘T::x’ because ‘T’ is a dependent scope
CLANG:  error: missing 'typename' prior to dependent type name 'T::x'

Another compelling case (to me at least) is when using typedefs to alias dependent types. In this case, there is no doubt about whether whatever follows the typedef keyword should be a type (right?), so why disambiguate anything?

To summarize: in the many cases where the compiler can easily deduce from the syntax and context whether the programmer means a type or variable, why is it still necessary to disambiguate?

EDIT

The comments and the suggested duplicate mention that specializations might complicate matters. For example (taken from an answer in the other thread):

struct B {
    typedef int result_type;
};

template<typename T>
struct C { }; // could be specialized!

template<typename T>
struct D : B, C<T> {
  void f() {
    // OK, member of current instantiation!
    // A::result_type is not dependent: int
    D::result_type r1;

    // error, not a member of the current instantiation
    D::questionable_type r2;

    // OK for now - relying on C<T> to provide it
    // But not a member of the current instantiation
    typename D::questionable_type r3;        
  }
};

I understand that C might be specialized for T, and whether C<T>::questionable_type exists can only be resolved on instantiation, but this doesn't change the fact that it has to be a type. The syntax is just demands it, so why disambiguate?

Community
  • 1
  • 1
JorenHeit
  • 3,877
  • 2
  • 22
  • 28
  • You might have specializations unknown to the compiler at this point. Also see [this](http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords) – quantdev Jan 13 '15 at 13:54
  • [This](http://stackoverflow.com/a/17579889/3002139) answer discusses exactly what you ask. – Baum mit Augen Jan 13 '15 at 14:00
  • It is worth emphasizing the **or by being used to name a base class**. That is `template struct A : T::x {};` compiles just fine. – rodrigo Jan 13 '15 at 14:01
  • @quantdev: True, but not relevant to the question of why `typename` is required even in a context where only a type-name would be allowed. (Presumably the answer is that trying to enumerate all the cases where it is required to avoid ambiguity would make the grammar horribly complicated, compared to simply requiring it for all dependent scopes. But I've no idea whether that's the "real" motivation for this rule.) – Mike Seymour Jan 13 '15 at 14:02
  • @MikeSeymour What you presume sounds reasonable, were it not that this seems already be implemented to a large extent (otherwise the errors would not be issued in such detail). – JorenHeit Jan 13 '15 at 14:04
  • 2
    @JorenHeit: It's one thing for some compilers to choose to implement a (perhaps rather difficult) diagnostic for some cases. It's quite another thing for the language to require it of all compilers, and to try to enumerate all the cases (and only those cases) where it's required. (Also, from a user's point of view, I'd find the simple rule "always use `typename` if there's a dependent scope" easier to follow than "figure out whether there might be an ambiguity, and use `typename` only in those cases", regardless of how easy or hard it makes the implemetor's job). – Mike Seymour Jan 13 '15 at 14:16
  • @MikeSeymour Hm, maybe... I only have little experience with parsers and compilers, so I can't really judge on the impact of demanding this from the implementation. However, from a user perspective I'd prefer not to use `typename` everywhere... it clutters up the code and complicates the syntax. The situation being actually ambiguous seems to be the exception rather than the rule in my experience. – JorenHeit Jan 13 '15 at 14:26
  • @BaummitAugen Please enlighten me, and tell me why it's a duplicate. Did you see my edit? Did I miss anything? – JorenHeit Jan 13 '15 at 14:38
  • @JorenHeit If you need clarification on another answer on this site, why not leave a comment *there* so the author (or someone else) can clarify in an edit. Your issue is definitely addressed in this question, the answers being not perfect is no reason for a new question, but a bounty or update on the original one. – Baum mit Augen Jan 13 '15 at 15:06
  • @BaummitAugen Except that the question you're referring to isn't explicitly asking what I want to know. If anything, I should put a bounty on the question that I linked to myself, and even that one isn't wording the question as I would like to. – JorenHeit Jan 13 '15 at 15:21

0 Answers0