3

このタプルタイプがある場合:

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

どうすればそれを横断できますか?フラットなタプルをトラバースする関数を書くことはできましたが、ネストされたタプルではできませんでした。

問題は、ネストされたタプルで考えられるすべての型を処理するテンプレート化された関数または型の実装にあるようです。次の場合が必要です。

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

これは、すべてのタイプのオーバーロード解決に最適な選択であり、タプルであるという情報が失われるため、タプルを再帰的に走査することはできません。タプルかどうかを判断しようとするクラスまたは関数を作成しようとすると、上記と同じ問題を持つ「偽」のケースに遭遇します。バージョンが見落とされます。

何かがタプルかどうかを確認するために私が知らない方法はありますか?

4

3 に答える 3

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 に答える
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 に答える