2

CRTP(不思議なことに繰り返されるテンプレートパターン)を使用すると、基本クラスにそれから派生したクラスの知識を提供できます。基本クラスから派生した各クラスのインスタンスを格納する配列を作成することはそれほど難しくありません(例を参照)。

class Base{
    public:
        static std::vector<Base *> m_derivedInstances;
};

template <class Derived>
class CRTPBase : public Base {
    public:
        static bool m_temp;
        static bool addInstance()
        {
            m_derivedInstances.push_back(new Derived);
            return true;
        }
};
template <class Derived>
CRTPBase<Derived>::m_temp = CRTPBase<Derived>::addInstance();

すべてのタイプの派生クラスのタイプリスト( http://www.research.ibm.com/designpatterns/pubs/ph-jun00.pdfを参照)を作成できるかどうか疑問に思いました。問題は、コンパイラがそれから派生する新しいクラスをBase検出するたびに、リストに新しい型を追加する必要があることですが、タイプリストは不変です(新しい型が追加された新しいリストを作成することは可能ですが、追加する私の知る限り、リストの要素は不可能です。最後に、次のようなものが必要です。

struct DerivedClassHolder {
    typedef Loki::TL::MakeTypeList</*list all derived classes here*/>::Result DerivedTypes;
};

最終的な目標は、から派生するすべてのクラスを反復処理できるようにすることBaseです。

4

2 に答える 2

3

これは、疑似タイプマップを使用して実行できます。以下は、boost::mplを使用したサンプルコードです。「Implem」の明示的な定義は、対応する各implemヘッダーのマクロを使用して行うことができます。

#include <iostream>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/empty_sequence.hpp>
#include <boost/type_traits/is_same.hpp>

using namespace boost::mpl;
using namespace boost;


// A type map. Implem #N of type Key is type (default: void)

template <typename Key, int N>
struct Implem
{
  public:
    typedef void type;
};


// Type vector building functions
// void, the default type, is used to stop the recursion

template <typename Key, int N = 1>
struct ImplemToList;

template <typename Key, typename Item, int N>
struct ImplemListItem
{
  public:
    typedef typename push_front<typename ImplemToList<Key, N + 1>::type, Item>::type type;
};

template <typename Key, int N>
struct ImplemToList
{
  public:
    typedef typename Implem<Key, N>::type item;
    typedef typename eval_if<is_same<item, void>,
                             identity<vector<> >,
                             ImplemListItem<Key, item, N> >::type type;
};


// Example code: an interface with two implems

class Interface
{
  public:
    virtual const char* name() const = 0;
};

class Implem1 : public Interface
{
  public:
    virtual const char* name() const { return "implem_1"; }
};

class Implem2 : public Interface
{
  public:
    virtual const char* name() const { return "implem_2"; }
};

template <>
struct Implem<Interface, 1>
{
  public:
    typedef Implem1 type;
};

template <>
struct Implem<Interface, 2>
{
  public:
    typedef Implem2 type;
};


void print(Interface const& i)
{
  std::cout << i.name() << std::endl;
}

int main()
{
  typedef ImplemToList<Interface>::type IList;
  for_each<IList>(&print);
}
于 2013-05-21T21:13:37.980 に答える
2

タイプリストは手動でのみ作成できます。あなたが言及する問題、不変性は克服できないものです。

于 2012-05-22T18:08:27.223 に答える