使用 CRTP 的模板中的继承类型
Inherited types in templates using CRTP
下面是 CRTP 定义自定义集合类型的基本用法:
template <class __B>
struct A
{
typedef std::vector<__B> collection_type;
};
struct B: public A<B>
{
collection_type X;
};
在模板中使用
template <typename __T>
struct C: public A<C<__T>>
{
// collection_type X; <--- this does not compile
typename A<C<__T>>::collection_type X;
};
为什么 C 需要 "typename ...::" 部分而 B 不需要?
struct B
是具体的class,不是模板,它的定义不依赖于任何参数。因此,当编译器从 A<B>
继承它时,它从模板 A
实例化 class A<B>
,在其中看到 collection_type
的定义并且很高兴。
struct C
是模板,所以A<C<__T>>
依赖于参数__T
。 A
可以专门化,因此编译器不知道 collection_type
实际是什么,甚至不知道它是否存在。所以,我们必须告诉编译器在哪里寻找 collection_type
(所以,A<C<__T>>::collection_type
),并且它是一个类型(所以 typename A<C<__T>>::collection_type
)。
下面是 CRTP 定义自定义集合类型的基本用法:
template <class __B>
struct A
{
typedef std::vector<__B> collection_type;
};
struct B: public A<B>
{
collection_type X;
};
在模板中使用
template <typename __T>
struct C: public A<C<__T>>
{
// collection_type X; <--- this does not compile
typename A<C<__T>>::collection_type X;
};
为什么 C 需要 "typename ...::" 部分而 B 不需要?
struct B
是具体的class,不是模板,它的定义不依赖于任何参数。因此,当编译器从 A<B>
继承它时,它从模板 A
实例化 class A<B>
,在其中看到 collection_type
的定义并且很高兴。
struct C
是模板,所以A<C<__T>>
依赖于参数__T
。 A
可以专门化,因此编译器不知道 collection_type
实际是什么,甚至不知道它是否存在。所以,我们必须告诉编译器在哪里寻找 collection_type
(所以,A<C<__T>>::collection_type
),并且它是一个类型(所以 typename A<C<__T>>::collection_type
)。