2016-08-11 5 views
5

は、どのようにタプルの長さを示すintテンプレート引数を持つ関数を実装し、その長さはstd ::タプルを生成することができるテンプレート引数によってその長さを与え?プロデュースのstd ::タプルは、C++で

など。

あなたが欲しいタイプを生成することができ index_sequenceとヘルパータイプの別名使用
func<2>() returns std::tuple<int, int>(); 
func<5>() returns std::tuple<int, int, int, int, int>(). 
+0

これまで何を試みましたか? – user2079303

+2

必須: 'std :: array'だけを使っていると考えていますか?タプル( 'std :: tuple_size'、' std :: get'など)とよく似た '配列'を使うことができ、これを多く単純化します。 –

+0

@ user2079303私の直感では、型のリストを保持し、Nから0までカウントダウンし、カウンタを減分するときにintをリストに追加します。 Nが0の場合、そのタプルを型リストで返します。しかし、私はそれを実行する方法を知らない。 – yuefengz

答えて

5

このAエイリアステンプレートを持つ再帰的なソリューションであり、C++ 11で実装可能です。

template <size_t I,typename T> 
struct tuple_n{ 
    template< typename...Args> using type = typename tuple_n<I-1, T>::template type<T, Args...>; 
}; 

template <typename T> 
struct tuple_n<0, T> { 
    template<typename...Args> using type = std::tuple<Args...>; 
}; 
template <size_t I,typename T> using tuple_of = typename tuple_n<I,T>::template type<>; 

たとえば"3倍のタプル"と書くことができます:

tuple_of<3, double> t; 
5

:それは一般的なケースでは、あなたはおそらくstd::arrayと良いだろうことを呼び出す価値がある

// Just something to take a size_t and give the type `int` 
template <std::size_t> 
using Integer = int; 

// will get a sequence of Is = 0, 1, ..., N 
template <std::size_t... Is> 
auto func_impl(std::index_sequence<Is...>) { 
    // Integer<Is>... becomes one `int` for each element in Is... 
    return std::tuple<Integer<Is>...>{}; 
} 

template <std::size_t N> 
auto func() { 
    return func_impl(std::make_index_sequence<N>{}); 
} 

を、(あなたの場合は使用できません)、std::arraystd::pairと同様にタプルのように動作します。

更新:C++ 11ではなく14+で作業していることを明確にしたので、index_sequenceの実装を取得し、どこかで関連付ける必要があります(hereはlibC++です)。

template <std::size_t... Is> 
auto func_impl(std::index_sequence<Is...>) -> std::tuple<Integer<Is>...> { 
    return std::tuple<Integer<Is>...>{}; 
} 

template <std::size_t N> 
auto func() -> decltype(func_impl(std::make_index_sequence<N>{})) { 
    return func_impl(std::make_index_sequence<N>{}); 
} 
+2

これはC++ 14です。 – Yakk

+0

C++ 11で実装することはできますか? – yuefengz

+1

@Fake yeahもし 'index_sequence'の実装を得て、その関数に明示的な戻り値型を追加できれば。あなたの質問に 'C++ 11'タグを付けるべきですか? –

3

昔ながらの再帰はあなたの友達です:

template<std::size_t N> 
auto array_tuple() { 
    return std::tuple_cat(std::tuple<int>{}, array_tuple<N-1>()); 
} 

template<> 
auto array_tuple<0>() { 
    return std::tuple<>{}; 
} 
+1

関数の 'auto'戻り型にC++ 14標準が必要であることを指定すると便利です。 –

+0

良い点です。私たちは完全にC++ 11に依存できますか? – yuefengz

2

あなたがC++ 14で大丈夫ならここで明示的な戻り値の型を持つfuncfunc_implのC++ 11のバージョンがありますソリューション、Ryan's answerは行く方法です。

はC++ 11を使用すると、次の操作を行うことができます(まだindex_sequenceに基づいての、それはC++ 11に実装可能です):それと

template <size_t N, class T, class = std::make_index_sequence<N>> 
struct n_tuple; 

template <size_t N, class T, size_t... Is> 
struct n_tuple<N, T, std::index_sequence<Is...>> { 
    template <size_t > 
    using ignore = T; 

    using type = std::tuple<ignore<Is>...>; 
}; 

template <size_t N, class T> 
using n_tuple_t = typename n_tuple<N, T>::type; 

template <size_t N> 
n_tuple_t<N, int> func() { 
    return n_tuple_t<N, int>{}; 
} 
+0

index_sequenceはまだC++ 14の機能です。それにも依存しないことは可能ですか? – yuefengz

+1

おそらく、私はindex_sequenceの実装をコピーすることができます。 – yuefengz

+0

@Fakeはい、回答に記載されているとおり、C++ 11で実装可能です – Barry

関連する問題