2014-12-09 2 views
4

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

template <typename T> 
class Foo { 
public: 
    T type; //This is my hack to get decltype of T 
}; 

template <typename T> 
class Bar { 
public: 

}; 

int main() { 
    for(auto& foo : fs) { 
     //Is there some way to get the decltype of the template without having to refer to some arbitrary T member of Foo? 
     auto bar = someFunction<decltype(foo.type)>(); 
    } 
} 

Is есть способ получить аргумент аргумента шаблона без этого взлома? Если нет, то каково наилучшее обходное решение для получения такого значения?

+3

Что такое 'fs' ...? –

+0

Это всего лишь вектор, содержащий эти объекты, извините, возможно, его оставили (или объяснили). Дело в том, что я использую auto, потому что я на самом деле перебираю кортеж, а затем над вектором (fs), поэтому я действительно хочу использовать auto, а затем извлекать из него тип шаблона. – Gerard

+0

Эта деталь важна. Векторы однородны. –

ответ

6

Вы можете создать type_traits:

template <typename C> 
struct get_template_type; 

template <template <typename > class C, typename T> 
struct get_template_type<C<T>> 
{ 
    using type = T; 
}; 

, а затем использовать его (предполагая, что C = Foo<T>, вы будете иметь T)

typename get_template_type<C>::type 

Live example

EDIT: Для классов с несколько параметров шаблона, чтобы получить первый:

template <template <typename > class C, typename T, typename ... Ts> 
struct get_template_type<C<T, Ts...>> 
{ 
    using type = T; 
}; 
+0

Спасибо, это то, что мне нужно! – Gerard

+0

Это не будет работать для шаблонов с аргументами или шаблонами по умолчанию с несколькими аргументами, такими как 'std :: vector'. – rubenvb

+0

Не могли бы вы добавить пример того, как использовать его в моем сценарии? Я думал, что у меня это есть, но я не совсем понимаю. – Gerard

1

Everything в стандартной библиотеке просто имеет класс локальных определений типов:

template<typename T> 
struct Bla 
{ using value_type = T; } 

Так что вы можете сделать:

template<typename T> 
void f(const T& t) 
{ 
    typename T::value_type some_var_with_template_type; 
} 

В качестве альтернативы, вы можете изменить функцию вызова:

template<template<typename> class Class, typename T> 
void f(const Class<T>& c) 
{ 
    T some_var_with_template_type; 
} 

Но это наложило бы ограничения об удобстве использования и общности. Например, если бы существовал Class с более чем одним параметром шаблона, это не сработало (хотя для этого можно было использовать вариативные шаблоны). VARIADIC версия шаблона:

template<template<typename, typename...> class Class, typename T, typename... ArgTypes> 
void f(const Class<T, ArgTypes...>& t) 
{ 
    T some_var_of_template_type; 
} 

Обратите внимание, как value_type ЬурейеГо на сегодняшний день самое чистое и наиболее идиоматическим решением.

Some code to show how the functions would need to be written and used.

+0

Также кажется правильным, спасибо – Gerard

+0

Спасибо за дополнительный образец кода! – Gerard

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