Variadic Templates(可変長テンプレート)を使えば実現できます。
まず、template<class A, class B, class C>
のテンプレート宣言をtemplate<class ...ElemTypes>
に変更し、tuple<A, B, C>
の部分をtuple<ElemTypes...>
のように可変長テンプレートにします。
この後が少々やっかいです。
cpp
1 get < 0 > ( res ) . push_back ( get < 0 > ( v [ i ] ) ) ;
2 get < 1 > ( res ) . push_back ( get < 1 > ( v [ i ] ) ) ;
3 get < 2 > ( res ) . push_back ( get < 2 > ( v [ i ] ) ) ;
4 . . .
5 get < N - 1 > ( res ) . push_back ( get < N - 1 > ( v [ i ] ) ) ;
をどうやって展開するかです。
これにはコンパイル時整数シーケンス、std::index_sequence
が利用可能です。
ヘルパ関数emplace_helper
を定義します。
emplace_helper
にはres
(の参照)、v[i]
、そしてtupleの要素型の可変長テンプレートをstd::index_sequence_for<ElemTypes...>
でindex_sequence<0, 1, 2, ..., N-1>
に変換したものを渡します。
最後に、ヘルパ関数の中でfold expression を用いて展開します。
cpp
1 template < class Tuple , class Elem , std :: size_t . . . Indices >
2 void emplace_helper ( Tuple & tup , Elem && elem , std :: index_sequence < Indices . . . > ) {
3 ( . . . , std :: get < Indices > ( tup ) . emplace_back ( std :: get < Indices > ( elem ) ) ) ;
4 // ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // fold expression
6 }
すると、次のように(この場合は左結合の)カンマ区切りの式を得ることができます。
((push_0 , push_1) , ...) , push_N-1
ここで push_N
は
std::get<N>(tup).emplace_back(std::get<N>(elem))
のことです
完全なコードを載せておきます。
cpp
1 # include <tuple>
2 # include <vector>
3 # include <type_traits>
4
5 template < class Tuple , class Elem , std :: size_t . . . Indices >
6 void emplace_helper ( Tuple & tup , Elem && elem , std :: index_sequence < Indices . . . > ) {
7 ( . . . , std :: get < Indices > ( tup ) . emplace_back ( std :: get < Indices > ( elem ) ) ) ;
8 // ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9 // fold expression
10 }
11
12 template < class . . . ElemTypes >
13 auto vt_to_tv ( std :: vector < std :: tuple < ElemTypes . . . >> const & v ) {
14 std :: tuple < std :: vector < ElemTypes > . . . > res { } ;
15 for ( auto const & elem : v )
16 { emplace_helper ( res , elem , std :: index_sequence_for < ElemTypes . . . > { } ) ; }
17 return res ;
18 }
19 # include <iostream>
20 # include <string>
21
22 int main ( ) {
23 std :: vector < std :: tuple < int , double , std :: string >> source {
24 { 1 , 1.1 , "one" } ,
25 { 2 , 2.2 , "two" }
26 } ;
27
28 auto [ int_vec , double_vec , string_vec ] = vt_to_tv ( source ) ;
29
30 for ( auto && elem : int_vec )
31 { std :: cout << elem << " " ; }
32 std :: cout << "\n" ;
33 for ( auto && elem : double_vec )
34 { std :: cout << elem << " " ; }
35 std :: cout << "\n" ;
36 for ( auto && elem : string_vec )
37 { std :: cout << elem << " " ; }
38 std :: cout << "\n" ;
39 // 1 2
40 // 1.1 2.2
41 // one two
42 }
Wandboxで実行する
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/05/19 09:55
2020/05/19 10:02 編集