2016-03-12 3 views
2

У меня есть функция с параметром шаблона, которую я знаю как std::tuple нескольких стандартных контейнеров C++ для разных типов элементов. Как я могу извлечь из этого тип, который является std::tuple типов элементов?Извлечение кортежа value_type из кортежа контейнеров в C++ 11

Например, предположим, что у меня есть следующие функции

template <typename TupOfCtrs> 
void doStuff(const TupOfCtrs& tupOfCtrs) { 
    using TupOfElements = /*extract a tuple type by applying CtrT::value_type to each container in tupOfCtrs and combining the results into an std::tuple*/; 
    MyHelperClass<TupOfElements> helper; 
} 

, и я знаю, что в настоящее время называется так:

std::list<Foo> l {/*...*/}; 
std::vector<Bar> v {/*...*/}; 
std::deque<Baz> d {/*...*/}; 
auto tup = std::make_tuple(l, v, d); 

В этом случае, я хочу тип TupOfElements помощник определяется как std::tuple<Foo, Bar, Baz>. Обратите внимание, что мне не нужно на самом деле создать кортеж, только чтобы получить его тип.

Как это можно достичь, возможно, используя библиотеку Boost::Fusion?

ответ

4

Вы можете сделать это даже в более простой форме без Boost, Fusion, как это:

// Template which takes one type argument: 
template <typename Tuple> struct TupOfValueTypes; 

// Only provide a definition for this template for std::tuple arguments: 
// (i.e. the domain of this template metafunction is any std::tuple) 
template <typename ... Ts> 
struct TupOfValueTypes<std::tuple<Ts...> > { 
    // This definition is only valid, if all types in the tuple have a 
    // value_type type member, i.e. the metafunction returns a type only 
    // if all types of the members in the std::tuple have a value_type 
    // type member, and a std::tuple can be constructed from these: 
    using type = std::tuple<typename Ts::value_type...>; 
}; 

template <typename TupOfCtrs> 
void doStuff(const TupOfCtrs& tupOfCtrs) { 
    using TupOfElements = typename TupOfValueTypes<TupOfCtrs>::type; 
    // ... 
} 

Но это, конечно, проще указать doStuff для std::tuple явно:

template <typename ... Ts> 
void doStuff(const std::tuple<Ts...> & tupOfCtrs) { 
    using TupOfElements = std::tuple<typename Ts::value_type...>; 
    // ... 
} 

PS : Также обратите внимание, что во многих случаях, если вам нужно просто иметь список типов, класс std::tuple является излишним и может немного повредить время компиляции. Лично я всегда использовал вместо простой TypeList-структуры:

template <typename ... Ts> struct TypeList 
{ using type = TypeList<Ts...>; }; 
+0

Awesome, спасибо! :) –

4

Если вы хотите doStuff взять std::tuple, сделать это явно:

template <class... Ts> 
void doStuff(std::tuple<Ts...> const& tupOfCtr) { ... } 

После того как вы этот параметр обновление, это просто вопрос вытягивания value_type:

template <class... Ts> 
void doStuff(std::tuple<Ts...> const& tupOfCtr) 
{ 
    using value_tuple = std::tuple<typename Ts::value_type...>; 
    // ... 
} 
Смежные вопросы