C++ integer_sequence


 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM