C++模板陷阱

Any*_*orn 23 c++ templates

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

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

我现在意识到模板括号被视为关系运算符.要执行预期的操作,需要以下奇怪的语法,cf 模板:模板函数与类的模板成员函数不兼容:

f.template bar<T>();
Run Code Online (Sandbox Code Playgroud)

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

int*_*nt3 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
    }
};
Run Code Online (Sandbox Code Playgroud)

问题是编译器不知道是否Base<T>将是默认模板或专用模板.专用版本可能没有int a成员,因此编译器不会认为它可用.但你可以告诉编译器它将与using指令一起出现:

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

或者,您可以明确表示您正在使用以下成员T:

void func {
    T::a++; // OK!
}
Run Code Online (Sandbox Code Playgroud)


Joh*_*itb 8

这个让我心烦意乱的是:

#include <vector>
using std::vector;

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

int main() {
  foo f;
  f.vector<int>(); // ambiguous!
}
Run Code Online (Sandbox Code Playgroud)

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

f.foo::vector<int>();
Run Code Online (Sandbox Code Playgroud)

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!
Run Code Online (Sandbox Code Playgroud)


Luc*_*lle 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.
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是它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
}
Run Code Online (Sandbox Code Playgroud)