【发布时间】:2013-01-22 08:47:37
【问题描述】:
我已经使用 CRTP 实施了一项策略。该策略要求Base 类有一个名为 foo 的函数:
template<typename Base>
struct Policy<Base> {
// ...
Base* b(){ return static_cast<Base*>(this); }
void do(){ b()->foo(); }
};
我有一个名为Widget 的类使用我的策略。 Widget 实现 foo 一切都很好:
struct Widget : Policy<Widget> {
// ...
void foo();
};
问题:我还有一个名为OldWidget的类型,它在名为oldFoo的函数中实现了foo的功能:
struct OldWidget : Policy<OldWidget> {
// ...
void oldFoo();
};
我不想想要修改 OldWidget(除了通过策略扩展它)。我不想想要使用AdaptedOldWidget:
struct AdaptedOldWidget : OldWidget, Policy<AdaptedOldWidget> {
void foo(){ oldFoo(); }
};
最好的办法是将我现有的 policy_traits 类扩展为:
template<typename T>
struct policy_traits {};
template<>
struct policy_traits<Widget> {
// typedefs...
member_function_name = foo;
};
template<>
struct policy_traits<OldWidget> {
// typedefs
member_function_name = oldFoo;
};
这样我就可以像这样实施政策:
template<typename Base>
struct Policy<Base> {
// ...
Base* b() { return static_cast<Base*>(this); }
void do(){ b()->policy_traits<Base>::member_function_name(); }
};
有没有办法在 C++ 中实现类似的东西?
建议的解决方案:我可以执行以下操作:
template<typename Base>
struct Policy<Base> : Policy_Member_Traits<Base> {
// ...
Base* b(){ return static_cast<Base*>(this); }
void do(){ foo_wrapper(); }
};
template<typename T> struct Policy_Member_Traits { };
template<> struct Policy_Member_Traits<Widget> {
void foo_wrapper(){ static_cast<T*>(this)->foo(); }
};
template<> struct Policy_Member_Traits<OldWidget> {
void foo_wrapper(){ static_cast<T*>(this)->oldFoo(); }
};
希望有更好更简单的方法来实现这一点。
【问题讨论】:
-
您不能专门针对
OldWidget制定策略吗? (否则,在the pretty printer code 中有一个检测成员函数存在的特征示例。) -
@KerrekSB 我不需要复制很多策略代码吗?我想重用策略中的所有内容,只需将函数名称替换为取决于类型的名称。我去看看漂亮的打印机代码,谢谢!
-
只是专门化调度(例如,制定另一个专门的“调度”策略)。
-
@KerrekSB 喜欢我刚刚提出的 Policy_Member_Traits 政策?没有更好的方法吗?它不是很干净,我需要一个 1) type_traits 类和 2) 每个类型的 member_function "traits" 类......这很奇怪。
-
好吧,在你的名字不好的
void do()(关键字警告!)中,你会说DispatchPolicy<Base>::dispatch_foo(b);或类似的东西,而DispatchPolicy模板只会包含相关的函数定义,专门个别案例。