2013-10-26 3 views
3

Если у меня есть этот тип кортежа:пересекающего вложенными C++ 11 кортежа

std::tuple<int, string, std::tuple<...>, int>

Как я могу пройти через него? Я смог написать функции, которые пересекают плоский кортеж, но не с вложенными кортежами.

Проблема, кажется, для любой реализации шаблонной функции или типа, который обрабатывает все мыслимые типы во вложенном наборе, должна быть этот случай:

template<typename T> 
void somefunc(T t) 
{ 
    // Do something to t 
} 

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

Есть ли способ, которым я не знаю, проверить, что-то является кортежем?

+0

Можете ли вы объяснить (псевдо-) код, что вы пытаетесь сделать? Вопрос мне не совсем понятен. –

+2

Нормальная перегрузка должна работать нормально. В чем проблема? –

+0

Вы хотите запустить 'some_func' один раз для каждого элемента в кортеже? Но если подэлемент * является * кортежем, вы хотите запустить 'some_func' над каждым элементом этого вместо этого? Рекурсивно весь путь вниз? –

ответ

0

Если вы хотите проверить, является ли тип T является кортежем, это должно работать:

#include <type_traits> 
#include <tuple> 

template<typename> struct is_tuple : std::false_type {}; 
template<typename... Ts> struct is_tuple<std::tuple<Ts...>> : std::true_type {}; 

static_assert(is_tuple<std::tuple<int>>::value, "Oops"); 
static_assert(!is_tuple<int>::value, "Oops"); 

int main() {} 
2

Просто перегружать функцию someFunc() для кортежей и типов без кортежей:

template<typename... Ts> 
void someFunc(const std::tuple<Ts...>& tuple) 
{ 
    /* traverse the elements of the tuple */ 
    traverse_tuple(tuple); 
} 

template<typename T> 
void someFunc(const T& value) 
{ 
    /* do something with the value */ 
} 

Где traverse_tuple - та же самая функция, которую вы реализовали для пересечения не-вложенных (плоских) кортежей. Он вызывает someFunc() для каждого члена кортежа.
Для реализации функции пересечения кортежей вы можете проверить this answer.

0

Вы можете специализироваться STRUCT/класс вместо специализировать функции: адаптировать следующие к вашему делу (http://ideone.com/VgIJfj):

namespace details 
{ 

template<std::size_t I = 0, typename FuncT, typename... Tp> 
inline typename std::enable_if<I == sizeof...(Tp), void>::type 
    for_each(const std::tuple<Tp...> &, FuncT) 
    { } 

template<std::size_t I = 0, typename FuncT, typename... Tp> 
inline typename std::enable_if<I < sizeof...(Tp), void>::type 
    for_each(const std::tuple<Tp...>& t, FuncT f) 
    { 
    f(std::get<I>(t)); 
    for_each<I + 1, FuncT, Tp...>(t, f); 
    } 

template <typename T> 
struct traverseType 
{ 
    void operator() (const T& t) const 
    { 
     std::cout << "it is a generic T:" << t << std::endl; 
    } 
}; 

template <> 
struct traverseType<int> 
{ 
    void operator() (int i) const 
    { 
     std::cout << "it is a int:" << i << std::endl; 
    } 
}; 

// needed by the for_each. 
struct traverseTypeCaller 
{ 
    template <typename T> 
    void operator() (const T& t) const 
    { 
     details::traverseType<T>()(t); 
    } 
}; 

template <typename ...T> 
struct traverseType<std::tuple<T...>> 
{ 
    void operator() (const std::tuple<T...>& t) const 
    { 
     std::cout << "it is a tuple:" << std::endl; 
     for_each(t, traverseTypeCaller()); 
    } 
}; 

} 

template <typename T> 
void traverseType(const T& t) 
{ 
    details::traverseTypeCaller()(t); 
} 
Смежные вопросы