刚才我不得不浏览网站,找出为什么模板类模板成员函数会出现语法错误:
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 ++模板的其他奇怪方面和问题是不是您认为是常识的东西?
答案 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::vector
和foo::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
…
}