C ++模板陷阱

时间:2009-12-09 23:26:58

标签: c++ templates

刚才我不得不浏览网站,找出为什么模板类模板成员函数会出现语法错误:

template<class C> class F00 {
   template<typename T> bar();
};
...
Foo<C> f;
f.bar<T>(); // syntax error here

我现在意识到模板括号被视为关系运算符。要执行预期的操作,需要使用以下奇怪的语法,参见Templates: template function not playing well with class's template member function

f.template bar<T>();

您遇到的C ++ / C ++模板的其他奇怪方面和问题是不是您认为是常识的东西?

4 个答案:

答案 0 :(得分:14)

我第一次从另一个模板化的类继承了一个模板化的类时,我被绊倒了:

template<typename T>
class Base {
    int a;
};

template<typename T>
class Derived : public Base<T> {
    void func() {
        a++; // error! 'a' has not been declared
    }
};

问题是编译器不知道Base<T>是默认模板还是专用模板。专用版本可能没有int a作为成员,因此编译器不会认为它可用。但是你可以告诉编译器,它将使用using指令:

template<typename T>
class Derived : public Base<T> {
    using Base<T>::a;
    void func() {
        a++; // OK!
    }
};

或者,您可以明确表示您使用的是T

的成员
void func {
    T::a++; // OK!
}

答案 1 :(得分:8)

这个让我心烦意乱:

#include <vector>
using std::vector;

struct foo {
  template<typename U>
  void vector();
};

int main() {
  foo f;
  f.vector<int>(); // ambiguous!
}

main中的最后一行是不明确的,因为编译器不仅在vector内查找foo,还从main开始查找非限定名称。因此它找到了std::vectorfoo::vector。要解决这个问题,你必须写

f.foo::vector<int>();

GCC并不关心这一点,并通过做直观的事情(调用成员)接受上述代码,其他编译器做得更好并且像comeau一样警告:

"ComeauTest.c", line 13: warning: ambiguous class member reference -- function
          template "foo::vector" (declared at line 8) used in preference to
          class template "std::vector" (declared at line 163 of
          "stl_vector.h")
        f.vector<int>(); // ambiguous!

答案 2 :(得分:5)

关于SO的模板问题的明星:缺少类型名称!

template <typename T>
class vector
{
  public:
    typedef T * iterator;
    ...
};

template <typename T>
void func()
{
    vector<T>::iterator it;           // this is not correct!

    typename vector<T>::iterator it2; // this is correct.
}

这里的问题是vector<T>::iterator是一个从属名称:它取决于模板参数。因此,编译器不知道iterator指定了一个类型;我们需要告诉他typename关键字。

模板内部类或模板成员/静态函数也是如此:它们必须使用template关键字消除歧义,如OP中所述。

template <typename T>
void func()
{
    T::staticTemplateFunc<int>();          // ambiguous

    T::template staticTemplateFunc<int>(); // ok

    T t;

    t.memberTemplateFunc<int>();          // ambiguous

    t.template memberTemplateFunc<int>(); // ok
}

答案 3 :(得分:4)

超出范围类成员函数定义:

template <typename T> 
class List {                     // a namespace scope class template 
  public: 
    template <typename T2>       // a member function template 
    List (List<T2> const&);      // (constructor) 
    … 
}; 
template <typename T> 
 template <typename T2> 
List<T>::List (List<T2> const& b) // an out-of-class member function 
{                                 // template definition 
    … 
} 
相关问题