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

后端 未结 3 823
Happy的楠姐
Happy的楠姐 2021-02-14 15:20

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:32

    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;-).

    0 讨论(0)
  • 2021-02-14 15:32

    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.

    0 讨论(0)
  • 2021-02-14 15:38

    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.

    0 讨论(0)
提交回复
热议问题