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

后端 未结 3 719
心在旅途
心在旅途 2021-02-14 14:48

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

struct Test 
{
    typedef int Type;
};

template < typename T > 
void         


        
3条回答
  •  余生分开走
    2021-02-14 15:28

    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 
    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 
    struct Foo {
      typename some_template::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(), for example), you have to add the template keyword before the function name, as in foo.template bar().

    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.

提交回复
热议问题