我一直在学习C ++模板,我遇到了一些奇怪的行为。考虑这个类结构(从原始代码中删除):
class A {
public:
std::vector <int> vec;
};
template <typename T> class B : public A { };
template <typename T> class C : public B<T> {
public:
using A::vec;
int test() {
return vec[1]; // OK
}
int test2() {
return vec.size(); // error: 'class A' has no member named 'size'
}
};
编译时,我在test2
收到错误,说class A
没有成员size
。但vec
应该是vector
对象,而不是A
的实例。实际上,如果我直接从C
而不是A
派生B<T>
,或从C
中删除模板,那么编译就可以了。
此外,如果我将以下方法添加到C
:
int test3() {
void ***v = vec; // error: cannot convert from
// 'std::vector<int,...>' to 'void***'
}
编译器说它无法从vector<int>
转换为void***
,所以它似乎知道vec
的正确类型。我在这里犯了错误,或者这可能是我的编译器中的错误?我正在使用Apple版的g ++ 4.2.1。编辑:似乎也出现在g ++的更高版本中。
感谢您的帮助!
第二次修改:如果我在this->vec.size()
中使用test2
而不是依赖using A::vec
声明,我的编译器会很高兴。
答案 0 :(得分:2)
首先,您的代码使用clang进行编译(请参阅here),并且不使用gcc进行编译。我也用VS2013编译它。
您的原始问题与编译器在模板中查找名称的方式有关。
标准§14.6.2:
模板定义中使用的非依赖名称可以使用 通常的名称查找和绑定在他们使用的点。
C++ FAQ也有一个很好的条目:
编译器在查找依赖基类(如B)时 查找非依赖名称(如vec)。
解决方案:
1。使用this->vec
(模板中始终隐式依赖)
int test2() {
return this->vec.size();
}
2。使用using B<T>::vec
3。直接使用B<T>
:
int test2() {
return B<T>::vec.size();
}
备注:强>
using A::vec;
,看起来像编译器错误(并注意using B<T>::A::vec;
有效)。