2017-11-24 10 views
4

どのようにして、variadicテンプレートへのパラメータパックの各パラメータ自体がパラメータパックであることを表現できますか?variadicテンプレートで入れ子になったパラメータパックを取る方法は?

template <typename... TS> 
void use_tuple(std::tuple<TS...> arg0); 

template <typename... TS0, typename... TS1> 
void use_tuple(std::tuple<TS0...> arg0, std::tuple<TS1...> arg1); 

私はuse_tupleはタプルの任意の数を取ることができるようにしたい:

は、このコードを検討してください。今、私はこのようにそれを記述する必要があります。

template <typename... TS0, typename... REST> 
void use_tuple(std::tuple<TS0...> arg0, REST... rest); 

void use_tuple(); // Terminates the recursion. 

しかし、私はこのようにそれを書きたい:

// Each ELEMENT in PACK_OF_PACKS is a parameter pack. 
template <(typename...)... PACK_OF_PACKS> 
void use_tuple(std::tuple<PACK_OF_PACKS...>... args); 

これはさえ可能ですか?もしそうなら、どうですか?そうでない場合は、他に何ができますか?このコードの私の目標は、すべてのタプルに含まれるのタイプになることです。

私の究極の目標は、このようなものです:

template <typename...> void foo(); 

use_tuple(std::tuple<int, float, char>{}, 
      std::tuple<double, short, std::string>{}, 
      std::tuple<std::function<void()>, std::vector<int>>{}); 
// Results in a call to 
// foo<int, float, char, double, short, std::string, 
//  std::function<void()>, std::vector<int>>(); 

しかし、私は渡されたタプルの数や要素の数に依存しない間接の小型、定数数でこれを実装したいですそれぞれにだから再帰はありません。

+1

何use_tuple 'の体は、(のstd ::タプル ...引数)が'のように見えるのでしょうか?それは、言語の一部ではない、 '... ...'拡張を持たなければならないでしょう。 – Caleth

+0

@Filipp - 'use_tuple 、std :: tuple 、std :: tuple 、... 'または' std :: tuple max66

+0

あなたの質問を編集して、タプルで何をしたいのかを明確にしてください。コンテキストについては、[this](https://stackoverflow.com/questions/47477177/how-to-take-nested-parameter-packs-in-variadic-templates#comment81909794_47477266) –

答えて

1

そうでない場合は、他に何ができますか?

理由だけTuples...としてタプル自体を渡し、そのuse_tupleの本体で種類を抽出していませんか?

template <typename...> 
using example = int; 

template <typename... Ts> 
void foo(Ts...) { } 

template <typename... Tuples> 
void use_tuple(Tuples...) 
{ 
    foo(typename types<Tuples>::template apply<example>{}...); 
} 

あなたはヘルパーtypesクラスを持つ型を抽出することができます。このコードの

template <typename Tuple> 
struct types; 

template <typename... Ts> 
struct types<std::tuple<Ts...>> 
{ 
    template <template <typename...> class T> 
    using apply = T<Ts...>; 
}; 

live example on wandbox

+0

私はあなたのアイデアが気に入っていますが、問題をある場所から別の場所に移動するだけであると思います。 N個のタプルをとる 'use_tuple'の代わりに、' foo'はN個のインスタンス化を行います。私はまったく同じジレンマを残しています。 – Filipp

+2

@Filipp:最後にタプルで何をしたいですか?あなたは最終的にパックを抽出し、展開する必要があります –

+0

はい、それは私の目標です。しかし、私の質問は、一度に1つのタプルを再帰的に分解するのではなく、これをワンショットで行う方法です。 – Filipp

1

私の目標は、すべてのタプルに含まれるタイプで取得することです。

すべてを一意のパックとして指定するかどうかはわかりません。 PACK_OF_PACKSは実際にそれを示唆している。この場合、std::tuple_catを使用することができます。この線に沿って
何か作業をする必要があります:

template<typename... T> 
void do_use_tuple(std::tuple<T...>) { 
    // T are the types you are looking for 
} 

template <typename... T> 
void use_tuple(T&&... tuple) { 
    return do_use_tuple(std::tuple_cat(std::forward<T>(tuple)...)); 
} 

あなたも値の転送に興味を持っていない場合は、単にdecltypeを使用すると、あなたは簡単にそれを得ることができます。

詳細はhereを参照してください。


あなたが一緒にパックすべてのパラメータを望んでいないと、一度にそれらを1つのタプルを探求したい場合は、代わりにこのような何かを行うことができます。

template<typename T> 
struct tag { using type = T; }; 

template<typename... T, typename F> 
void use_one(std::tuple<T...> &&, F f) { 
    F(tag<T>{}...); 
} 

template <typename... T> 
void use_tuple(T&&... tuple) { 
    int arr = { 0, 
     (use_one(std::forward<T>(tuple), [](auto... tag) { 
      // tag::type contains the types of each 
      // parameter of a tuple, a tuple at a time 
     }), 0)... 
    }; 
    (void)arr; 
} 

それは調整するのは簡単ですラムダと他の関数が関与している場合は、値にもアクセスします。

+0

skypjack、私は 'tuple_cat'を認識していますが、私が見てきたすべての実装は、一度に1つまたは2つのタプルを再帰的に分解することによって実装されています。私はこれを避け、代わりにコンパイラがすべてのパラメータパックを一度に推論するように推論させるようにしたいと思います。ヴィットリオの答えのコメントを参照してください。 – Filipp

+0

@Filippまあ、ラムダの例では、再帰的にそれをしません。 – skypjack

0

次のようなものがあると思います(C++ 17)。 私はを推奨しません。 1つは明らかにstd::tuple_catを好むべきです。

http://coliru.stacked-crooked.com/a/c64f2cb9a79af3e2

#include <array> 
#include <iostream> 
#include <tuple> 
#include <utility> 

//////////////////////////////////////////////////////////////////////////////// 

template<class... Ts> 
void foo() { 
    std::cout << __PRETTY_FUNCTION__ << std::endl; 
} 

//////////////////////////////////////////////////////////////////////////////// 

namespace detail { 

struct Index { 
    std::size_t outer{};// identify the tuple 
    std::size_t inner{};// identify the element in the tuple 
}; 

template<std::size_t... ns, class... Tuples> 
constexpr void use_tuple(std::index_sequence<ns...>, Tuples...) { 
    constexpr auto inds = [&]() { 
    std::array<Index, sizeof...(ns)> inds{}; 
    std::size_t n = 0; 

    for(std::size_t outer=0; outer<sizeof...(Tuples); ++outer) { 
     std::size_t size = std::begin({std::tuple_size<Tuples>::value...})[outer]; 
     for(std::size_t inner=0; inner<size; ++inner) inds[n++] = {outer, inner}; 
    } 

    return inds; 
    }(); 

    using TupleTuple = std::tuple<Tuples...>; 

    foo< 
    std::tuple_element_t< 
     inds[ns].inner, 
     std::tuple_element_t<inds[ns].outer, TupleTuple> 
    >... 
    >(); 
} 

}// detail 

template<class... Tuples> 
constexpr void use_tuple(Tuples... tuples) { 
    constexpr std::size_t N = (std::tuple_size<Tuples>{} + ...); 
    detail::use_tuple(std::make_index_sequence<N>{}, std::move(tuples)...); 
} 

//////////////////////////////////////////////////////////////////////////////// 

int main() { 
    std::tuple<int, unsigned, int> t0; 
    std::tuple<double, float> t1; 
    std::tuple<char, bool, bool, int> t2; 

    use_tuple(t0, t1, t2); 

    return 0; 
} 
関連する問題