在 C++ 中将基于策略的设计与 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;
}
不幸的是,这无法编译,在我看来像是循环类型依赖:
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>’
如果有人能发现明显的错误,或者在策略中成功混合 CRTP,我将不胜感激任何帮助。
I'm attempting to write a policy-based host class (i.e., a class that inherits from its template class), with a twist, where the policy class is also templated by the host class, so that it can access its types. One example where this might be useful is where a policy (used like a mixin, really), augments the host class with a polymorphic clone() method. Here's a minimal example of what I'm trying to do:
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;
}
This, unfortunately, fails to compile, in what seems to me like circular type dependency:
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>’
If anyone can spot an obvious mistake, or has successfuly mixing CRTP in policies, I would appreciate any help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
事实上,问题是由于当您从策略继承时尚未看到
HostPtr
声明。有一些关于这些声明在实例化模板中可见的确切语义的讨论,这具有相当复杂的问题,请参阅 此缺陷报告。但就您而言,情况很清楚:在类主体之前,没有代码可以看到类成员的任何声明,因此您的代码失败。您可以将类型作为模板参数传递
如果有更多类型,您可能决定传递特征
In fact the problem is due to
HostPtr
declaration not having seen yet when you inherit from the policy. There is some discussion about the exact semantics where these declarations are visible by instantiated templates, which has pretty complex issues, see this defect report.But in your case, the situation is clear: Before the class body, no code can see any declaration of class members, and so your code fails. You could pass the type as a template argument
If there are more types, you may decide to pass a trait