1

CRTPを使用してポリシーを実装しました。ポリシーでは、Baseクラスにfooという関数が必要です。

template<typename Base>
struct Policy<Base> {
  // ...
  Base* b(){ return static_cast<Base*>(this); }
  void do(){ b()->foo(); }
};

Widgetポリシーを使用するというクラスが1つあります。Widget実装fooし、すべてが正常です:

struct Widget : Policy<Widget> {
  // ...
  void foo();
};

問題::という名前OldWidgetの関数での機能を実装するというタイプもあります。foooldFoo

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(); }
};

うまくいけば、これを達成するためのより簡単な方法があるはずです。

4

2 に答える 2

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)(); }
};
于 2013-01-22T09:01:56.753 に答える
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);
}
于 2013-01-22T09:19:07.783 に答える