Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do you sometimes need to write `typename T` instead of just `T`?

Tags:

c++

sfinae

I was reading the Wikipedia article on SFINAE and encountered following code sample:

struct Test 
{
    typedef int Type;
};

template < typename T > 
void f( typename T::Type ) {} // definition #1

template < typename T > 
void f( T ) {}                // definition #2

void foo()
{
    f< Test > ( 10 ); //call #1 

    f< int > ( 10 );  //call #2 without error thanks to SFINAE
}

Now I've actually written code like this before, and somehow intuitively I knew that I needed to type "typename T" instead of just "T". However, it would be nice to know the actual logic behind it. Anyone care to explain?

like image 273
StackedCrooked Avatar asked Aug 08 '09 00:08

StackedCrooked


People also ask

Why is typename needed?

" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.

What is typename template?

In template definitions, typename provides a hint to the compiler that an unknown identifier is a type. In template parameter lists, it's used to specify a type parameter.

How do you use type names?

You must add the keyword typename to the beginning of this declaration: typename A::C d; You can also use the keyword typename in place of the keyword class in template parameter declarations.


3 Answers

The short version that you need to do typename X::Y whenever X is or depends on a template parameter. Until X is known, the compiler can't tell if Y is a type or a value. So you have to add typename to specify that it is a type.

For example:

template <typename T>
struct Foo {
  typename T::some_type x; // T is a template parameter. `some_type` may or may not exist depending on what type T is.
};

template <typename T>
struct Foo {
  typename some_template<T>::some_type x; // `some_template` may or may not have a `some_type` member, depending on which specialization is used when it is instantiated for type `T`
};

As sbi points out in the comments, the cause of the ambiguity is that Y might be a static member, an enum or a function. Without knowing the type of X, we can't tell. The standard specifies that the compiler should assume it is a value unless it is explicitly labelled a type by using the typename keyword.

And it sounds like the commenters really want me to mention another related case as well: ;)

If the dependant name is a function member template, and you call it with an explicit template argument (foo.bar<int>(), for example), you have to add the template keyword before the function name, as in foo.template bar<int>().

The reason for this is that without the template keyword, the compiler assumes that bar is a value, and you wish to invoke the less than operator (operator<) on it.

like image 177
jalf Avatar answered Oct 18 '22 19:10

jalf


In general, C++'s syntax (inherited from C) has a technical defect: the parser MUST know whether something names a type, or not, otherwise it just can't solve certain ambiguities (e.g., is X * Y a multiplication, or the declaration of a pointer Y to objects of type X? it all depends on whether X names a type...!-). The typename "adjective" lets you make that perfectly clear and explicit when needed (which, as another answer mentions, is typical when template parameters are involved;-).

like image 21
Alex Martelli Avatar answered Oct 18 '22 19:10

Alex Martelli


Basically, you need the typename keyword when you are writing template code (i.e. you are in a function template or class template) and you are referring to an indentifier that depends on a template parameter that might not be known to be a type, but must be interpreted as a type in your template code.

In your example, you use typename T::Type at definition #1 because T::Type depends on the template parameter T and might otherwise be a data member.

You don't need typename T at definition #2 as T is declared to be a type as part of the template definition.

like image 3
CB Bailey Avatar answered Oct 18 '22 20:10

CB Bailey