Вопрос

Использование CRPP (любопытно повторяющаяся шаблон шаблона) Вы можете предоставить базовый класс со знанием классов, полученных из него. Нетственно создать массив, который хранит экземпляр каждого класса, который вытекает из базового класса (см. Пример)

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.

Это было полезно?

Решение

Это можно сделать, используя псевдо-карту.Вот какой-то пример код с использованием Boost :: MPL.Явное определение «IMMEM» можно сделать с помощью макроса в каждом соответствующем заголовке императора.

#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);
}
.

Другие советы

Ваш тип тепластаста может быть создан только вручную.Проблема, которую вы упоминаете, неизменяемость, является непреодолимой.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top