我何时应该在使用模板时使用关键字“typename”

时间:2010-11-19 17:44:06

标签: c++ templates syntax typename

我最近一直在做一个小项目,我无法弄明白......

我使用typename模板获得了一个包含类的.h文件。在那堂课里面有一个私人课程。

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


        };      
};

当我想定义类“Something”

的功能时出现问题

我是这样做的(在.inl文件中)

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
}

所以窃听部分在定义部分......我是否必须告诉编译器返回类型(在本例中为Node *)使用typename模板(如:typename Node*)?那参数怎么样? typename const Node&

基本上,我何时必须指定函数/参数是否使用模板?

感谢您的时间。

4 个答案:

答案 0 :(得分:5)

对于Function1,您需要告诉编译器Node是什么 - 在这种情况下,它是Something<T>内的嵌套类型。因为它依赖于T(它是一个从属名称),所以你需要告诉编译器它是一个类型,所以你必须把它写成typename Something<T>::Node。问题是可能有T Something<T>::Node实际上不是Something<T>类型(即如果您部分专门化Index)。

对于const T&,你所拥有的很好 - const T只是对T的引用,编译器知道{{1}}是什么。

答案 1 :(得分:3)

简单规则:如果typename部分取决于模板参数,则每次使用Class::Type语法命名类型时,都需要使用Class关键字。 (Class部分可能是模板参数,也可能是类模板中的typedef等。)

编辑:关于嵌套类作用域规则也存在一些混淆。这主要与typename问题无关,因此这是一个非模板示例。

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

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

Inner的全名是Outer::Inner。但您也可以在类Inner的范围内使用较短的名称Outer,包括func的所有声明。在func的定义中,返回类型不在Outer的范围内,因此全名是必需的。但是在(之后,函数参数在Outer的范围内,所以短名称是可以的。

将此与原始示例的模板相结合,因为Outer的等效值为Something<T>,您需要使用typename关键字来说明Something<T>::Node

答案 2 :(得分:2)

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

答案 3 :(得分:1)

typenameclass在模板类型参数列表中是等效的:

template <class T> class C;

相同
template <typename T> class C;

需要typename的地方是指dependent names

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