Вызов конструктора параметра шаблона - PullRequest
2 голосов
/ 03 января 2012

Учитывая шаблонный фабричный метод, я хотел бы вызвать различные конструкторы, основанные на конструкторах, которые предоставляет параметр шаблона:

template<typename T>
T* Factory::create()
{
  if (hasOnlyDefaultConstructor<T>())
    return new T();
  else
    return new T(this);
}

Две проблемы:

  • Если T не имеет конструктора T (Factory *), тогда возникают проблемы компиляции.
  • Как написать hasOnlyDefaultConstructor ()?

В общем, я хотел бы следующее:

template<typename T>
T* Factory::create()
{
  if (hasDefaultConstructor<T>())
    return new T();
  else if (hasUnaryConstructor<T>())
    return new T(create());
  else if (hasBinaryConstructor<T>())
    return new T(create(), create());
  else ....
}

Есть ли способ достичь этого в C ++? Я понимаю проблемы, если есть несколько конструкторов для выбора компилятора, но допустим, что мы передаем только типы T, которые имеют ровно один открытый конструктор.

class A 
{
  A(B* b);
}

class B 
{
  B(C* c, D* d);
}  

A* a = Factory::create<A>(); // same as A* a = new A(new B());
B* b = Factory::create<B>(); // same as B* b = new B(new C(), new D());

Разве нельзя написать общую функцию create (), которая могла бы создавать экземпляры как B, так и A?

Ответы [ 2 ]

3 голосов
/ 03 января 2012

Ваш пример немного странный ...

Я бы предположил, что вы хотите что-то вроде:

template<typename T>
T* Factory::create()
{
    return new T();
}

template<typename T, typename P0>
T* Factory::create(P0&& p0)
{
    return new T(std::forward<P0>(p0));
}

template<typename T, typename P0, typename P1>
T* Factory::create(P0&& p0, P1&& p1)
{
    return new T(std::forward<P0>(p0), std::forward<P1>(p1));
}

или с вариационными шаблонами:

template<typename T, typename... Args>
T* Factory::create(Args&&... args)
{
    return new T(std::forward<Args>(args)...);
}

РЕДАКТИРОВАТЬ:

На основе комментариев ниже ... все еще странно из представления управления памятью.

template<typename T>
struct factory;

template<>
struct factory<A>
{
   static A* create(){return new A(new B());}
}

template<>
struct factory<B>
{
   static B* create(){return new B(new C(), new D());}
}

int main()
{
     A* a = factory<A>::create();
     B* b = factory<B>::create();
     return 0;
}
1 голос
/ 03 января 2012

Вы можете захотеть это:

struct X
{
  enum {TYPE = 0;}// has default constructor
  X() {}
};


struct A
{
  enum {TYPE = 1;}
  typedef B P;
  A(P* p) {}
};

struct B
{
  enum {TYPE = 2;}
  typedef C P1;
  typedef D P2;
  B(P1* p1, P2* p2) {}
};

template<T, type> //type default = 0
struct FactoryDetail<T>
{
  static T* create(){return new T(); } 
};

template<T>
struct FactoryDetail<T, 1>
{
  static T* create(){return new T(new typename T::P()); } 
};

template<T>
struct FactoryDetail<T, 2>
{
  static T* create(){return new T(new typename T::P1(), new typename T::P2()); } 
};

//final Factory
template<T>
struct Factory
{
  static T* create(){return FactoryDetail<T, T::TYPE>::create(); } 
};

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

...