3

如果我有这个元组类型:

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

我怎样才能穿越它?我已经能够编写遍历平面元组的函数,但不能编写嵌套元组。

问题似乎在于处理嵌套元组中所有可能类型的模板化函数或类型的任何实现,必须存在这种情况:

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

这最终成为每种类型的重载解决方案的最佳选择,并且您无法递归遍历元组,因为您丢失了它是元组的信息。如果您尝试编写一个尝试确定它是否是元组的类或函数,您仍然会遇到“假”情况,它与上述问题相同,因为它最终匹配每种类型并且元组专门化版本被忽略。

有没有一种我不知道的方法来检查某物是否是元组?

4

3 回答 3

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()元组的每个成员。
对于元组遍历函数的实现,您可以检查这个答案

于 2013-10-26T11:47:44.030 回答
0

您可以专门化结构/类而不是专门化功能:根据您的情况调整以下内容(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);
}
于 2013-10-26T13:40:30.767 回答
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() {}
于 2013-10-26T11:13:37.487 回答