我已使用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
的类型,它在名为foo
的函数中实现oldFoo
的功能:
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(); }
};
必须有一种更好的方法来实现这一目标。
答案 0 :(得分:3)
首先:所有功能的签名必须相同。然后你可以在policy_traits
内设置一个带有成员函数地址的静态成员,这样你就可以在以后(使用Policy
模板)调用所需的函数。
typedef void (*void_memfn_type)();
template<>
struct policy_traits<Widget> {
static void_memfn_type const member_function_name = &Widget::foo;
};
template<>
struct policy_traits<OldWidget> {
static void_memfn_type const member_function_name = &OldWidget::oldFoo;
};
然后:
template<typename Base>
struct Policy<Base> {
// ...
Base* b() { return static_cast<Base*>(this); }
void do(){ b()->policy_traits<Base>::(*member_function_name)(); }
};
答案 1 :(得分:2)
以下是有选择性专业化的示例。首先,一些示例类:
#include <iostream>
struct Foo
{
void foo() const { std::cout << "Foo::foo\n"; }
void bar() const { std::cout << "Foo::foo\n"; }
};
struct Biz
{
void old_foo() const { std::cout << "Fiz::old_foo\n"; }
void bar() const { std::cout << "Fiz::foo\n"; }
};
struct Fiz
{
void foo() const { std::cout << "Biz::foo\n"; }
void old_bar() const { std::cout << "Biz::old_foo\n"; }
};
现在的特点:
template <typename T> struct Dispatch
{
static void foo(T const & x) { x.foo(); }
static void bar(T const & x) { x.bar(); }
};
template <> void Dispatch<Biz>::foo(Biz const & x) { x.old_foo(); }
template <> void Dispatch<Fiz>::bar(Fiz const & x) { x.old_bar(); }
这是一个用法示例:
template <typename T> void dispatch(T const & x)
{
Dispatch<T>::foo(x);
Dispatch<T>::bar(x);
}
int main()
{
Foo f;
Biz b;
Fiz c;
dispatch(f);
dispatch(b);
dispatch(c);
}