简体   繁体   中英

When should I use the keyword "typename" when using templates

I've been working lately on a small project, and I couldn't figure out something..

I've been given a .h file that was containing a class, using a typename template. Inside that class there was a private class.

template <typename T>
class Something
{
public:
        Something();
        ~Something();

        Node* Function1(int index);
        int Index(const T& id);


private:
        class Node()
        {
                public:
                T id;

                //Imagine the rest for the Node


        };      
};

The problem occured when I wanted to define the functions of the class "Something"

Here's how I was doing it (in a .inl file)

template<typename T>
Node* Something::Function1(int index) //Is the return type well written?
{
        // returns the node at the specified index
}

template<typename T>
int Something::Index(const T& id) //Is the parameter type well specified?
{
        // returns the index of the node with the specified id
}

So the bugging part was in the definitions part... Do I have to tell the compiler that the return type (in this case Node*) uses the typename template (like this: typename Node* ) ? And what about the parameter ? typename const Node& ?

So basically, when do I have to specify wether the function/parameter uses a template?

Thanks for your time.

For Function1 , you need to tell the compiler what Node is -- in this case, it's a nested type inside Something<T> . Because it's dependent on T (it's a dependent name), you need to tell the compiler it's a type, so you must write it as typename Something<T>::Node . The issue is that there might be some T for which Something<T>::Node isn't actually a type (ie if you partially specialize Something<T> ).

For Index , what you have is fine -- const T& is just a reference to a const T , and the compiler knows what T is.

The simple rule: You need to use the typename keyword every time you name a type using the Class::Type syntax, if the Class part depends on a template parameter. (The Class part might be a template parameter, or it might be a typedef in your class template, etc.)

Edit: There's also some confusion about nested class scoping rules. This is mostly independent of the typename issue, so here's a non-template example.

class Outer {
public:
  class Inner {
  };
  Inner* func(Inner* obj);
};

Outer::Inner* func(Inner* obj)
{
}

The full name of Inner is Outer::Inner . But you can also use the shorter name Inner anywhere from the scope of class Outer , including all of the declaration of func . At the definition of func , the return type is NOT in the scope of Outer , so the full name is necessary. But after the ( , the function parameters ARE in the scope of Outer , so the short name is okay.

Combining this with the template-ness of the original example, since the equivalent of Outer is Something<T> , you need the typename keyword to say Something<T>::Node .

template<typename T>
typename Something<T>::Node * Something::Function1(int index) //Is the return type well written?
{
        // returns the node at the specified index
}

typename and class are equivalent in template type parameter list:

template <class T> class C;

is the same as

template <typename T> class C;

Where the typename is required is when referring to dependent names :

template <typename T> struct A {
    typedef typename T::some_type container;
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM