2011-01-07 2 views
1

Предположим, у меня есть много классов с их коллегами «* Pack» в именовании. Например, если у меня есть класс Moo, у меня есть MooPack, если у меня есть Foo, у меня также есть FooPack.Stringify и Unstringify аргументы шаблона

Я хочу иметь C++ шаблонной функции, которая возвращает FooPack из Foo

template <class X, class XPack> 
XPack packify(X input){ 
    ... 
} 

Можно ли это сделать без того, чтобы указать аргумент шаблона? На данный момент, это должно быть сделано так:

Moo moo; 
MooPack mooppey = packify<Moo, MooPack>(moo); 

Если требуется только шаблон аргумента Moo, что некрасиво спецификация шаблона немного может уйти, но кроме использования #defines, который не является на самом деле лучшее решение тоже, все равно этого не делает.

Есть ли способ, или мне придется ждать C++ 0x?

ответ

5

Вам не нужно указывать Moo, просто MooPack, потому что moo выведет аргумент для вас. Однако я бы предположил, что вы делаете MooPack typedef или вложенным классом (называемым Pack) внутри самого Moo, и в этом случае вы можете легко получить к нему доступ с помощью typename X :: Pack внутри шаблона.

class Moo { 
public: 
    class Pack { 
     ... 
    }; 
}; 
template<typename T> typename T::Pack packify(T t) { 
    ... 
} 

// usage 

Moo m; 
Moo::Pack p = packify(m); 
+0

Ах да, я думаю, что указание только одного аргумента на самом деле достаточно приемлемо (два аргумента просто выглядят уродливыми). Эта вложенная вещь класса - отличная идея, но я не могу изменить существующие объявления классов. – kamziro

+2

Вам даже не нужно встраивать класс '* Pack', вам просто нужно предоставить вложенный в него typedef. Использование такое же, как в приведенном выше примере. Это довольно распространенный шаблон (называемый «metafunction»). –

1

В качестве ответа по DeadMG уже упоминалось вам не нужно явно указать тип параметра, как это может быть выведено автоматически (если это второй вместо первого параметра шаблона). Так как вы сказали, что вы не можете изменить тип объявления, чтобы сформировать связь между классами, я хотел бы предложить маршрут черты для этого (думаю StD :: iterator_traits):

template<typename T> struct pack_traits; 
template<> struct pack_traits<Moo> { typedef MooPack Pack; }; 
...//traits for other packifable classes 

template<typename T> pack_traits<T>::Pack packify(T val){...} 
... 
Moo moo; 
MooPack mooppey = packify(moo); 

Таким образом, вы можете вызвать функцию без вручную указывая аргументы шаблона, без необходимости изменять сами классы.

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