【发布时间】:2019-03-20 10:27:12
【问题描述】:
我看到了一个在 CRTP 模式的基类中使用派生类型特征的习惯用法,如下所示:
template<typename Derived>
struct traits;
template<typename Derived>
struct Base {
using size_type = typename traits<Derived>::size_type;
};
template <typename T>
struct Derived1 : Base<Derived1<T>>{
using size_type = size_t;
void print(){ std::cout << "Derived1" << std::endl; }
};
template <typename T>
struct traits<Derived1<T>> {
using size_type = size_t;
};
int main()
{
using T = float;
Derived1<T> d1;
d1.print();
}
我的理解是,这个成语的目的是为了延迟Base类的size_type的实例化。我感到困惑的是,这种模式似乎只有在派生类本身是模板化的情况下才有效。例如,如果我们将代码更改为:
template<typename Derived>
struct traits;
template<typename Derived>
struct Base {
using size_type = typename traits<Derived>::size_type;
};
struct Derived1 : Base<Derived1>{
using size_type = size_t;
void print(){ std::cout << "Derived1" << std::endl; }
};
template <>
struct traits<Derived1> {
using size_type = size_t;
};
int main()
{
Derived1 d1;
d1.print();
}
然后我们得到错误
prog.cc: In instantiation of 'struct Base<Derived1>':
prog.cc:21:19: required from here
prog.cc:18:58: error: invalid use of incomplete type 'struct traits<Derived1>'
using size_type = typename traits<Derived>::size_type;
^
prog.cc:14:8: note: declaration of 'struct traits<Derived1>'
struct traits;
^~~~~~
prog.cc: In function 'int main()':
prog.cc:33:9: error: 'Derived1' is not a template
Derived1<float> d1;
谁能给我一个解释,说明为什么模板化的派生类可以编译,但非模板化的类不能?
【问题讨论】:
-
"我的理解是这个成语的目的是延迟 Base 类的 size_type 的实例化" 不,CRTP 的目的是将信息注入到一个类中,例如编译时多态可用。我相信你试图做的是滥用 CRTP。您正处于实例化时间模板的副作用中,与 CRTP 完全无关。