【发布时间】:2013-04-19 06:35:18
【问题描述】:
当使用curiously recurring template pattern 时,如果我尝试从基类引用它们,我将无法引用属于派生类的类型定义只有; gcc 抱怨no type named 'myType' in class Derived<...>。这似乎与使用 typedef、模板和奇怪的重复关系可能实现的不一致。
考虑:
/* crtp.cpp */
#include <iostream>
using namespace std;
// case 1. simple.
class Base {
public:
typedef int a_t;
a_t foo;
};
class Derived : public Base {
a_t bar;
};
// case 2. template.
template<typename T>
class tBase {
public:
typedef T b_t;
T foo;
};
template <typename T>
class tDerived : public tBase<T> {
typename tBase<T>::b_t bar;
};
// case 3. curiously recurring.
template <typename T, typename D>
class tCuriousBase {
public:
typedef T c_t;
c_t foo;
};
template <typename T>
class tCuriousDerived : public tCuriousBase<T,tCuriousDerived<T> > {
typename tCuriousBase<T,tCuriousDerived<T> >::c_t bar;
};
// case 4. curiously recurring with member reference.
template <typename T, typename D>
class tCuriousMemberBase {
public:
T foo;
T get() {
return static_cast<D*>(this)->bar;
}
};
template <typename T>
class tCuriousMemberDerived : public tCuriousMemberBase<T, tCuriousMemberDerived<T> > {
public:
T bar;
tCuriousMemberDerived(T val) : bar(val) {}
};
// case 5. curiously recurring with typedef reference.
template <typename T, typename D>
class tCuriousTypeBase {
public:
typedef T d_t;
d_t foo;
typename D::c_t baz;
};
template <typename T>
class tCuriousTypeDerived : public tCuriousTypeBase<T, tCuriousTypeDerived<T> > {
public:
typedef T c_t;
typename tCuriousTypeBase<T,tCuriousTypeDerived<T> >::d_t bar;
};
// entry point
int main(int argc, char **argv) {
Derived::a_t one = 1;
tDerived<double>::b_t two = 2;
tCuriousDerived<double>::c_t three = 3;
double four = tCuriousMemberDerived<double>(4).get();
tCuriousTypeBase<double, tCuriousDerived<double> >::d_t five = 5;
// tCuriousTypeDerived<double>::d_t six = 6; /* FAILS */
cout << one << endl;
cout << two << endl;
cout << three << endl;
cout << four << endl;
cout << five << endl;
// cout << six << endl;
}
从 (1) 中,我们看到 typedef 确实是从基类继承到派生类;基类中声明的 typedef 可以通过派生类访问。
从 (2) 中,我们看到如果两个类都是模板,这仍然是正确的。
从(3)中,我们看到这种 typedef 继承仍然可以存在于存在奇怪重复的模板关系的情况下;我们在three 的声明中通过派生类引用基类的 typedef。
从 (4) 中,我们看到派生类的成员变量可以很容易地从基类中访问。
从 (5) 中,我们看到我们可以访问定义在模板参数上的 typedef(这在我们使用与继承无关的类型声明 five 时有效)。
然而,一旦我们在 (6) 中将模板参数设为派生类,typedef 突然变得不可访问,尽管它看起来与派生类中的任何成员变量一样定义良好。
这是为什么?
【问题讨论】:
-
不要太担心“奇怪地反复出现”这个词组。如果你彻底分析它,它并不是真的“反复出现”。
-
它在哪个编译器上失败了什么消息?
-
@PeterWood:在这个例子中,它以
error: no type named 'c_t' in 'class tCuriousTypeDerived<double>'失败。
标签: c++ templates gcc typedef crtp