Eit*_*tan 9 c++ polymorphism policy templates crtp
我正在尝试编写一个基于策略的宿主类(即一个继承自其模板类的类),其中一个扭曲,其中策略类也由宿主类进行模板化,以便它可以访问其类型.这可能有用的一个例子是策略(实际上像mixin一样使用),使用多态clone()方法扩充宿主类.这是我正在尝试做的最小例子:
template <template <class> class P>
struct Host : public P<Host<P> > {
typedef P<Host<P> > Base;
typedef Host* HostPtr;
Host(const Base& p) : Base(p) {}
};
template <class H>
struct Policy {
typedef typename H::HostPtr Hptr;
Hptr clone() const {
return Hptr(new H((Hptr)this));
}
};
Policy<Host<Policy> > p;
Host<Policy> h(p);
int main() {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
遗憾的是,这不能编译,在我看来像循环类型依赖:
try.cpp: In instantiation of ‘Host<Policy>’:
try.cpp:10: instantiated from ‘Policy<Host<Policy> >’
try.cpp:16: instantiated from here
try.cpp:2: error: invalid use of incomplete type ‘struct Policy<Host<Policy> >’
try.cpp:9: error: declaration of ‘struct Policy<Host<Policy> >’
try.cpp: In constructor ‘Host<P>::Host(const P<Host<P> >&) [with P = Policy]’:
try.cpp:17: instantiated from here
try.cpp:5: error: type ‘Policy<Host<Policy> >’ is not a direct base of ‘Host<Policy>’
Run Code Online (Sandbox Code Playgroud)
如果有人能发现一个明显的错误,或者在政策中成功地混合了CRTP,我将不胜感激.
实际上,问题是由于HostPtr您从政策继承时尚未看到声明.有一些关于确切语义的讨论,其中这些声明是由实例化模板可见的,这些模型具有相当复杂的问题,请参阅此缺陷报告.
但在你的情况下,情况很明显:在类主体之前,没有代码可以看到类成员的任何声明,因此你的代码失败了.您可以将类型作为模板参数传递
template <template <class,class> class P>
struct Host : public P<Host<P>, Host<P>* > {
typedef P<Host<P> > Base;
Host(const Base& p) : Base(p) {}
};
template <class H, class Hptr>
struct Policy {
typedef Hptr HostPtr;
HostPtr clone() const {
return Hptr(new H((Hptr)this));
}
};
Run Code Online (Sandbox Code Playgroud)
如果有更多类型,您可以决定传递特征
template <class Host>
struct HTraits {
typedef Host *HostPtr;
// ...
};
template <template <class,class> class P>
struct Host : public P<Host<P>, HTraits< Host<P> > > {
typedef P<Host<P> > Base;
Host(const Base& p) : Base(p) {}
};
template <class H, class Htraits>
struct Policy {
typedef typename Htraits::HostPtr HostPtr;
HostPtr clone() const {
return Hptr(new H((Hptr)this));
}
};
Run Code Online (Sandbox Code Playgroud)