1 #include <tuple> 2 #include <iostream> 3 #include <utility> 4 5 template<typename F, typename T, std::size_t... I> 6 decltype(auto) apply_impl(F f, const T& t, std::index_sequence<I...>) 7 { 8 return f(std::get<I>(t)...); 9 } 10 11 template<typename F, typename T> 12 decltype(auto) apply(F f, const T& t) 13 { 14 return apply_impl(f, t, std::make_index_sequence<std::tuple_size<T>::value>()); 15 } 16 17 18 int main() 19 { 20 auto tp = std::make_tuple(1, 'A', 1.2); 21 22 auto ld = [](int arg1, char arg2, double arg3)->int{ 23 std::cout << "call func(" << arg1 << ", " << arg2 << ", " << arg3 << ")" << std::endl; 24 return 0; 25 }; 26 27 int ret= apply(ld, tp); 28 }
參考:https://blog.poxiao.me/p/unpacking-a-tuple-to-call-a-function-in-cpp14/
這里需要注意的是,函數的模板參數推演。C++03/98時,是單個實參,推導出單個模板類型,例如t推導出T。C++11/14開始,參數包也能推導了,例如:
1 template<int... Is> 2 struct sequence{}; 3 4 template<int... Is> 5 void foo( sequence<Is...> sq ) 6 { 7 (std::cout << ... << Is); 8 } 9 10 int main() 11 { 12 foo( sequence<1,3,5,7,9>() ); 13 }
既然interger_sequence這樣重要,這里給出一個實現。
1 #include <iostream> 2 3 // This is the type which holds sequences 4 template <int ... Ns> struct sequence {}; 5 6 // First define the template signature 7 template <int ... Ns> struct seq_gen; 8 9 // Recursion case 10 template <int I, int ... Ns> 11 struct seq_gen<I, Ns...> 12 { 13 // Take front most number of sequence, 14 // decrement it, and prepend it twice. 15 // First I - 1 goes into the counter, 16 // Second I - 1 goes into the sequence. 17 using type = typename seq_gen< 18 I - 1, I - 1 , Ns...>::type; 19 }; 20 21 // Recursion abort 22 template <int ... Ns> 23 struct seq_gen<0, Ns...> 24 { 25 using type = sequence<Ns...>; 26 }; 27 28 template <int N> 29 using sequence_t = typename seq_gen<N>::type; 30 31 32 template<int...Is> 33 void show( sequence<Is...>){ 34 ( ((std::cout << " ") << Is) , ...) ; 35 } 36 37 int main(){ 38 show( sequence_t<10>() ); 39 }
參考:https://blog.galowicz.de/2016/06/24/integer_sequences_at_compile_time/
原理解析:
sequence_t<10>類型是這個類型的別名:seq_gen<10>::type 見第29行
seq_gen<10>唯一能匹配的模板特化為:seq_gen<10, int...Ns> 。現在這個Ns是空列表{}。這是1個模板參數變成2組模板參數質的飛躍。我們用偽代碼seq_gen<10, {}>表示
seq_gen<10, {}>::type 等價於seq_gen<10-1,10-1, {}>::type即seq_gen<9,9, {}>::type 見第18行
seq_gen<9,9, {}>唯一能匹配的模板特化為:seq_gen<9, int...Ns>。現在這個Ns是列表{9}。我們用偽代碼seq_gen<9, {9}>表示.
seq_gen<9, {9}>::type 等價於seq_gen<9-1,9-1, {9}>::type即seq_gen<8,8, {9}>::type
seq_gen<8,8, {9}>唯一能匹配的模板特化為:seq_gen<8, int...Ns>。現在這個Ns是列表{8,9}。我們用偽代碼seq_gen<8, {8,9}>表示.
......
seq_gen<0, {0,1,2,3,4,5,6,7,8,9}>唯一能匹配的模板特化為第22行,遞歸終結特化。
seq_gen<0, int...Ns>:::type等價於sequence<0,1,2,3,4,5,6,7,8,9>. 結束。
還有更具有效率的算法,有空可研究:https://stackoverflow.com/questions/17424477/implementation-c14-make-integer-sequence