Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
239 views
in Technique[技术] by (71.8m points)

c++ - Use of typename keyword with template function parameters

In C++, the typename keyword is needed so the compiler can disambiguate between nested types and nested values in templates. However, there are certain situations where no ambiguity is possible, such as when a derived class inherits from a nested class type.

template <class T>
class Derived : public T::type
{ };

Here the typename keyword is not required, and is in fact not even allowed. This makes sense, because the context removes the ambiguity. Here, T::type must refer to a type, since you obviously can't inherit from a value.

I would think the same thing would hold true for function template parameters.

template <class T>
void foo(const T::type& v)
{

}

In this case, the context makes it clear that T::type must refer to a type, since a function parameter can't be a value. Yet, the compiler doesn't accept this. It wants const typename T::type&. This seems inconsistent. Why does the language allow the implicit assumption of a nested type in the context of inheritance, but not in the context of function parameters? In both cases there can be no ambiguity, so why the need for typename in one but not the other?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If you slightly change your declaration, you get an entire different story

template <class T>
void foo(T::type& v);

That isn't unambiguous anymore. It could declare a variable of type void that is initialized by a bit-wise AND expression. The entire declaration would be templated. Of course, this semantically is all nonsense, but it syntactically is alright.

The appearance of a single const syntactically makes it unambiguous, but it's too much context dependence to make this work in a compiler. It has to remember that it read a const or any other such thing, and when it parses the T::type after it will need to remember to take this name as a type. It would also further bloat the already complicated Standard beyond belief.

Let's again change your function declaration

template <class T>
void foo(const T::type);

Not even the appearance of const in there provides for a unambiguous parse. Should it be a function declaration with an unnamed parameter, or should it be a function declaration with an invalid parameter name that misses its type? A parameter's name is parsed by a declarator-id, which can also be a qualified name. So here, the const will belong to the type specifiers, while the T::type will be parsed by the compiler as the name of the parameter, in absence of a typename. That is totally nonsense too, but is syntactically valid.

In the case of base-class names name lookup itself states that non-type names are ignored. So you get omission of typename for free: The name that name lookup yields to more higher level modules of the compiler either refers to a type, or name lookup will have given an error.

I have written a FAQ entry about Where to put the "template" and "typename" on dependent names.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...