Шаблон C ++ указывает тип по Enum - PullRequest
0 голосов
/ 19 февраля 2011

Я столкнулся с проблемой: Я хочу создать функцию, которая вызывает конкретный конструктор типа шаблона в зависимости от перечисления, которое получит функция. Под этим я подразумеваю:

  typedef   ____ (Class<whatever>::*tabType)(int flag);

  template<typename T>
  static Class*  Class<t>::createClassInstance(enum precision)
  {
    static const ___ createTab[] = {
    Class<int>,
    Class<double>
    }
   return (new createTab[precision](1));
  }

Ответы [ 4 ]

1 голос
/ 19 февраля 2011

Существует несколько способов достижения такого рода вещей, но звучит так, будто вы хотите создать массив (или карту) фабричных методов (по одному для каждого класса), проиндексированных переменной enum. Каждый вызывает соответствующий конструктор и возвращает новый объект этого типа.

Конечно, чтобы это имело какой-либо смысл, все классы должны происходить из общей базы.

0 голосов
/ 21 февраля 2011

Расширяя ваш пример, работает что-то вроде следующего:

enum Prec {INT, DOUBLE};

struct Base
{
    virtual ~Base () = 0 {}
};

template<typename T> struct Class : public Base
{
    static Base* create (int flag) {return new Class<T> (flag);}
    Class (int flag) {}
};

typedef Base* (*Creator) (int flag);

Base* createClassInstance (Prec prec)
{
    static const Creator createTab[] = {
        Class<int>::create,
        Class<double>::create
    };

    return createTab[prec] (1);
}

int main (int argc, char* argv[])
{
    Base* c = createClassInstance (DOUBLE);

    return 0;
}
0 голосов
/ 19 февраля 2011

Я бы сказал, просто создайте std::map, который отображает enum на заводскую функцию (boost::function<>).Затем вы просто добавляете одну запись для каждого типа, который вам нужен, с соответствующим enum.На самом деле построить фабричные функции.Вы можете иметь некоторую функцию static Create() для каждого класса и сохранить указатель на функцию.Или вы можете использовать Boost.Lambda конструктор / деструктор функторы.Или вы можете использовать Boost.Bind для создания функторов, которые оборачивают фабричную функцию, для которой требуется некоторое количество параметров.Вот пример:

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/lambda/construct.hpp>
#include <map>

struct Base { };

struct Derived1 : public Base { };

struct Derived2 : public Base {
  static Base* Create() { return new Derived2; };
};

struct Derived3 : public Base {
  int value;
  Derived3(int aValue) : value(aValue) { };
  static Base* Create(int aValue) { return new Derived3(aValue); };
};

enum DerivedCreate { ClassDerived1, ClassDerived2, ClassDerived3 };

int main() {
  std::map< DerivedCreate, boost::function< Base*() > constructor_map;
  constructor_map[ClassDerived1] = boost::lambda::new_ptr<Derived1>();
  constructor_map[ClassDerived2] = &Derived2::Create;
  constructor_map[ClassDerived3] = boost::bind(&Derived3::Create, 42);

  //now you can call any constructor as so:
  Base* ptr = constructor_map[ClassDerived2]();
};

Возможно, я допустил некоторые небольшие синтаксические ошибки, но в основном вы должны быть в состоянии заставить вышеописанную работу.Кроме того, тот факт, что у вас есть несколько шаблонов классов, не играет никакой роли, поскольку они создаются для конкретного класса (например, Class<int> или Class<double>), они похожи на любой другой класс, и приведенная выше идея должна оставаться действительной.*

0 голосов
/ 19 февраля 2011

Если значение перечисления является динамическим в качестве аргумента функции, вам придется использовать либо таблицу диспетчеризации, либо switch / if-else.Обратите внимание, что ваш псевдокод не дает четкого объяснения этому требованию.Скажите, какую именно функцию createInstance вы хотите определить и как она будет вызываться?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...