2013-06-13 4 views
3

У меня есть эта функция:Передача параметров конструктора к функции шаблона фабрике

template <class T> 
T *allocate() 
{ 
    T *obj = new(top) T(); 
    top += sizeof(T); 
    return obj; 
} 

Теперь он работает прекрасно объекты СОЗДАЮТ с конструкторами по умолчанию, но как создать объекты, которые должны быть переданы новые параметры?

Я знаю, что это может быть достигнуто с использованием C++ 11 variadic template s, но как я могу это сделать без функциональности C++ 11? (По-видимому, моя версия VS2012 еще не поддерживает эту функцию, но я хотел бы знать, как это сделать без этой функции, даже если обновление исправит ее)

+0

Вы можете эмулировать вариативные шаблоны, используя множество перегрузок для параметров 0, 1, 2, ... N. Boost.Preprocesser может использоваться для их создания. – Angew

+0

Вы можете попытаться реализовать его с помощью макроса C, хотя это * опасно * и не рекомендуется большинством советов по C++ – GuLearn

ответ

4

Не существует языковой функции, которая заменяет вариативные шаблоны (конечно, иначе они не были бы изобретены).

Вы можете указать несколько перегрузок, которые принимают до N параметров (для разумного выбора N). Каждая перегрузка была бы идеальной - перенаправить свой аргумент в конструктор T.

Так кроме вашего нульарного шаблона функции:

template <class T> 
T *allocate() 
{ 
    T *obj = new(top) T(); 
    top += sizeof(T); 
    return obj; 
} 

Вы будете иметь унарный шаблон функции:

template <class T, class P1> 
T *allocate(P1&& p1) 
{ 
    T *obj = new(top) T(std::forward<P1>(p1)); 
    top += sizeof(T); 
    return obj; 
} 

бинарный шаблон функции:

template <class T, class P1, class P2> 
T *allocate(P1&& p1, P2&& p2) 
{ 
    T *obj = new(top) T(std::forward<P1>(p1), std::forward<P2>(p2)); 
    top += sizeof(T); 
    return obj; 
} 

трехкомпонентной шаблон функции :

template <class T, class P1, class P2, class P3> 
T *allocate(P1&& p1, P2&& p2, P3&& p3) 
{ 
    T *obj = new(top) T(std::forward<P1>(p1), std::forward<P2>(p2), 
         std::forward<P3>(p3)); 
    top += sizeof(T); 
    return obj; 
} 

И так далее (вы понимаете). Если вы не согласны с репликацией кода, вы можете выяснить некоторые макросы, которые уменьшат боль, но они не устраняют ее, особенно если вы не любите макросы.

Не забудьте:

#include <utility> 

Чтобы получить доступ к std::forward<>().

+0

Не является ли 'std :: forward' частью C++ 11? OP спрашивал, как это сделать без функциональности C++ 11. – zindorsky

+2

@zindorsky: Я думаю, что OP интересуется функциями, поддерживаемыми VC11. Поддерживается совершенная переадресация –

1

Это не просто вариационные шаблоны, которые вам нужны, но и отличные возможности пересылки C++ 11.

Если у вас нет функциональности C++ 11, можно подделать его, по крайней мере, для установленного ограничения количества параметров. Но это непросто или красиво. Например, см. Ускорение реализации boost::tuple.

1

Если вы ча использовать импульс, вы могли бы использовать boost::in_place_factory вместо http://www.boost.org/doc/libs/1_35_0/libs/utility/in_place_factories.html

template <class InplaceFactory> 
T *allocate(InplaceFactory const & fac) 
{ 
    T *obj = reinterpret_cast<T*>(top); 
    fac.template apply<T>(obj) 
    top += sizeof(T); 
    return obj; 
} 

и польза:

T * a = allocate(boost::in_place(val, boost::ref(ref_value))); 

PS Не делать так:

T * a = allocate(boost::in_place()); 

Вы Можно добавить перегрузки:

T *allocate(){ return allocate(boost::in_place()); } 
0

Вы, возможно, придется взять дизайн хит на этом, если вы не хотите использовать varadic шаблон:

struct empty {}; 
template<typename ObjectType,unsigned int ARG_LENGTH = 0, 
     typename arg0=empty, 
     typename arg1=empty, 
     typename arg2=empty, 
     typename arg3=empty, 
     typename arg4=empty> 
ObjectType* allocate(const arg0& a0, 
        const arg1& a1, 
        const arg2& a2, 
        const arg3& a3, 
        const arg4& a4){ 
    ObjectType * obj = 0; 
    switch(ARG_LENGTH){ 
    case 0: obj = new(top) ObjectType();break; 
    case 1: obj = new(top) ObjectType(arg0);break; 
    case 2: obj = new(top) ObjectType(arg0,arg1);break; 
    case 3: obj = new(top) ObjectType(arg0,arg1,arg2);break; 
    case 4: obj = new(top) ObjectType(arg0,arg1,arg2,arg3); break; 
    default: obj = new(top) ObjectType(); break; 
    } 
    top += sizeof(T); 
    return obj; 
} 

Не уверен, если это будет компилировать, но вы получите идею ,

Смежные вопросы