日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
可能學(xué)了假的編程?C++新標準難點解析之可變模板參數(shù)

 前言

C++的新特性--可變模版參數(shù)(variadic templates)是C++新增的最強大的特性之一,它對參數(shù)進行了高度泛化,它能表示0到任意個數(shù)、任意類型的參數(shù)。相比C++98/03,類模版和函數(shù)模版中只能含固定數(shù)量的模版參數(shù),可變模版參數(shù)無疑是一個巨大的改進。然而由于可變模版參數(shù)比較抽象,使用起來需要一定的技巧,所以它也是C++中最難理解和掌握的特性之一。雖然掌握可變模版參數(shù)有一定難度,但是它卻是C++11中最有意思的一個特性,本文希望帶領(lǐng)讀者由淺入深地認識和掌握這一特性,同時也會通過一些實例來展示可變參數(shù)模版的一些用法。

變模版參數(shù)的展開

可變參數(shù)模板和普通模板的語義是一樣的,只是寫法上稍有區(qū)別,聲明可變參數(shù)模板時需要在typename或class后面帶上省略號“...”。比如我們常常這樣聲明一個可變模版參數(shù):template

 
 
 
  1. template 
  2. void f(T... args);

 省略號的作用:

1.聲明一個參數(shù)包T... args,這個參數(shù)包中可以包含0到任意個模板參數(shù); 2.在模板定義的右邊,可以將參數(shù)包展開成一個一個獨立的參數(shù)。

省略號的參數(shù)稱為“參數(shù)包”,它里面包含了0到N(N>=0)個模版參數(shù)。我們無法直接獲取參數(shù)包args中的每個參數(shù)的,只能通過展開參數(shù)包的方式來獲取參數(shù)包中的每個參數(shù),這是使用可變模版參數(shù)的一個主要特點,也是最大的難點,即如何展開可變模版參數(shù)。

可變模板參數(shù)分類:

1.可變模版參數(shù)函數(shù)

2.可變模版參數(shù)類

打印可變模版參數(shù)函數(shù)的參數(shù)個數(shù)

 
 
 
  1. #include 
  2. #include 
  3. using namespace std;
  4. template 
  5. void print(Type ...data) 
  6. {
  7.     cout << sizeof...(data) << endl;
  8. }
  9. int main() 
  10. {
  11.     print();
  12.     print(1);
  13.     print(1, "ILoveyou");
  14.     print(1, 2, 3.4, "IMissyou");
  15.     return 0;
  16. }

 上面的例子中,print()沒有傳入?yún)?shù),所以參數(shù)包為空,輸出的size為0,后面兩次調(diào)用分別傳入兩個和三個參數(shù),故輸出的size分別為2和3。由于可變模版參數(shù)的類型和個數(shù)是不固定的,所以我們可以傳任意類型和個數(shù)的參數(shù)給函數(shù)print。這個例子只是簡單的將可變模版參數(shù)的個數(shù)打印出來,如果我們需要將參數(shù)包中的每個參數(shù)打印出來的話就需要通過一些方法了。

展開可變模版參數(shù)函數(shù)的方法一般有兩種:

1.通過遞歸函數(shù)來展開參數(shù)包。

2.逗號表達式來展開參數(shù)包。

遞歸方式展開參數(shù)包

通過遞歸函數(shù)展開參數(shù)包,需要提供一個參數(shù)包展開的函數(shù)和一個遞歸終止函數(shù),遞歸終止函數(shù)正是用來終止遞歸的,如下面的例子:

 
 
 
  1. #include 
  2. using namespace std;
  3. //遞歸終止函數(shù)
  4. void print()
  5. {
  6.     cout << "遞歸終止函數(shù)" << endl;
  7. }
  8. //展開函數(shù)
  9. template 
  10. void print(T data,Type...exData)
  11. {
  12.     cout << data << endl;
  13.     print(exData...);
  14. }
  15. int main()
  16. {
  17.     print(1, 2, 3, 4);
  18.     return 0;
  19. }

 上例會輸出每一個參數(shù),直到為空時輸出"遞歸終止函數(shù)"。展開參數(shù)包的函數(shù)有兩個,一個是遞歸函數(shù),另外一個是遞歸終止函數(shù),參數(shù)包exData...在展開的過程中遞歸調(diào)用自己,每調(diào)用一次參數(shù)包中的參數(shù)就會少一個,直到所有的參數(shù)都展開為止,當沒有參數(shù)時,則調(diào)用非模板函數(shù)print終止遞歸過程。當然上述終止函數(shù)也可以寫成帶參數(shù)函數(shù)模板:

 
 
 
  1. template 
  2. void print(T data)
  3. {
  4.  cout<
  5. }

 接下來用模板函數(shù)作為終止函數(shù)寫一個不限參求和函數(shù),具體實現(xiàn)代碼如下:

 
 
 
  1. #include 
  2. using namespace std;
  3. //遞歸終止函數(shù)
  4. template 
  5. Type sum(Type t) 
  6. {
  7.     return t;
  8. }
  9. //展開函數(shù)
  10. template 
  11. T sum(T a, Type ...b) 
  12. {
  13.     return a + sum(b...);
  14. }
  15. int main()
  16. {
  17.     cout << sum(1, 2, 3, 4) << endl;
  18.     cout << sum(1, 2, 3) << endl;
  19.     return 0;
  20. }

 sum在展開參數(shù)包的過程中將各個參數(shù)相加求和,參數(shù)的展開方式和前面的打印參數(shù)包的方式是一樣的。

逗號表達式展開參數(shù)包

遞歸函數(shù)展開參數(shù)包是一種標準做法,也比較好理解,但也有一個缺點,就是必須要一個重載的遞歸終止函數(shù),即必須要有一個同名的終止函數(shù)來終止遞歸,這樣可能會感覺稍有不便。有沒有一種更簡單的方式呢?其實還有一種方法可以不通過遞歸方式來展開參數(shù)包,這種方式需要借助逗號表達式和初始化列表。比如前面打印函數(shù)可以改成這樣:

 
 
 
  1. #include 
  2. using namespace std;
  3. //遞歸終止函數(shù)
  4. template 
  5. void print(T data) 
  6. {
  7.     cout << data << "\t";
  8. }
  9. template 
  10. void print(Type ...exData) 
  11. {
  12.     int array[] = { (print(exData),0)... };
  13. }
  14. int main()
  15. {
  16.     print(1, 2, 3);
  17.     cout << endl;
  18.     print("張三", 1, 3);
  19.     return 0;
  20. }

 這個數(shù)組的目的純粹是為了在數(shù)組構(gòu)造的過程展開參數(shù)包。我們可以把上面的例子再進一步改進一下,將函數(shù)作為參數(shù),就可以支持lambda表達式了,從而可以少寫一個遞歸終止函數(shù)了,具體代碼如下:

C++中新特性之:initializer_list詳解

C++11提供的新類型,定義在 頭文件中。

 
 
 
  1. template< class T >
  2. class initializer_list;

 下面稍微介紹一下initializer_list

一個initializer_list當出現(xiàn)在以下兩種情況的被自動構(gòu)造:

  1. 當初始化的時候使用的是大括號初始化,被自動構(gòu)造。包括函數(shù)調(diào)用時和賦值
  2. 當涉及到for(initializer: list),list被自動構(gòu)造成initializer_list對象

也就是說initializer_list對象只能用大括號{}初始化??截愐粋€initializer_list對象并不會拷貝里面的元素。其實只是引用而已。而且里面的元素全部都是const的。下面一個例子可以幫助我們更好地理解如何使用initializer_list:

 
 
 
  1. #include 
  2. #include 
  3. #include 
  4. using namespace std;
  5. template 
  6. struct S 
  7. {
  8.     vector v;
  9.     S(initializer_list l) : v(l) {
  10.         cout << "constructed with a " << l.size() << "-elements lists" << endl;
  11.     }
  12.     void append(std::initializer_list l) {
  13.         v.insert(v.end(), l.begin(), l.end());
  14.     }
  15.     pair c_arr() const {
  16.         return { &v[0], v.size() };
  17.     }
  18. };
  19. template 
  20. void templated_fn(T arg) {
  21.     for (auto a : arg)
  22.         cout << a << " ";
  23.     cout << endl;
  24. }
  25. int main() 
  26. {
  27.     S s = { 1, 2, 3, 4, 5 };                
  28.     s.append({ 6, 7 , 8 });        
  29.     for (auto n : s.v)
  30.         cout << ' ' << n;
  31.     cout << endl;
  32.     for (auto x : { -1, -2, 03 })  
  33.         cout << x << " ";
  34.     cout << endl;
  35.     auto al = { 10, 11, 12 }; 
  36.     templated_fn >({ 7, 8, 9 }); 
  37.     templated_fn>({ 3, 5, 7 });       
  38.     return 0;
  39. }

 可變模版參數(shù)類

std::tuple就是一個可變模板類

 
 
 
  1. template< class... Types >
  2. class tuple;

 這個可變參數(shù)模板類可以攜帶任意類型任意個數(shù)的模板參數(shù):

 
 
 
  1. tuple tp1 = std::make_tuple(1);
  2. tuple tp2 = std::make_tuple(1, 2.5);
  3. tuple tp3 = std::make_tuple(1, 2.5, “”);

 可變參數(shù)模板的模板參數(shù)個數(shù)可以為0個,所以下面的定義也是也是合法的:

 
 
 
  1. tuple<> tp;

可變參數(shù)模板類的參數(shù)包展開的方式和可變參數(shù)模板函數(shù)的展開方式不同,可變參數(shù)模板類的參數(shù)包展開需要通過模板特化和繼承方式去展開,展開方式比可變參數(shù)模板函數(shù)要復(fù)雜。

模版偏特化和遞歸方式來展開參數(shù)包

基本的可變參數(shù)模板類

 
 
 
  1. //前向聲明
  2. template
  3. struct Sum;
  4. //基本定義
  5. template
  6. struct Sum
  7. {
  8.     enum { value = Sum::value + Sum::value };
  9. };
  10. //遞歸終止
  11. template
  12. struct Sum
  13. {
  14.     enum { value = sizeof (Last) };
  15. };
  16. int main()
  17. {
  18.     cout << Sum::value << endl;
  19.     return 0;
  20. }

 繼承方式展開參數(shù)包

 
 
 
  1. //整型序列的定義
  2. template
  3. struct IndexSeq{};
  4. //繼承方式,開始展開參數(shù)包
  5. template
  6. struct MakeIndexes : MakeIndexes {};
  7. // 模板特化,終止展開參數(shù)包的條件
  8. template
  9. struct MakeIndexes<0, Indexes...>
  10. {
  11.     typedef IndexSeq type;
  12. };
  13. int main()
  14. {
  15.     using T = MakeIndexes<3>::type;
  16.     cout <
  17.     return 0;
  18. }

 可變參數(shù)模版消除重復(fù)代碼

C++11之前如果要寫一個泛化的工廠函數(shù),這個工廠函數(shù)能接受任意類型的入?yún)?,并且參?shù)個數(shù)要能滿足大部分的應(yīng)用需求的話,我們不得不定義很多重復(fù)的模版定義,比如下面的代碼:

 
 
 
  1. #include 
  2. using namespace std;
  3. template
  4. T* Instance(Args... args)
  5. {
  6.     return new T(args...);
  7. }
  8. class A
  9. {
  10. public:
  11.     A(int a) :a(a) {}
  12.     A(int a, int b) :a(a) {}
  13.     A(int a, int b,string c) :a(a) {}
  14.     void print() 
  15.     {
  16.         cout << a << endl;
  17.     }
  18.     int a;
  19. };
  20. class B 
  21. {
  22. public:
  23.     B(int a, int b) :a(a), b(b) {}
  24.     void print()
  25.     {
  26.         cout << a << endl;
  27.         cout << b << endl;
  28.     }
  29.     int a;
  30.     int b;
  31. };
  32. int main()
  33. {
  34.     A* pa = Instance(1);
  35.     B* pb = Instance(1, 2);
  36.     pa->print();
  37.     pb->print();
  38.     pa = Instance(100, 2);
  39.     pa->print();
  40.     pa = Instance(100, 2,"Loveyo");
  41.     pa->print();
  42.     return 0;
  43. }

萬能函數(shù)

 
 
 
  1. template  
  2. class  MyDelegate 
  3. public: 
  4.     MyDelegate(T* t, R  (T::*f)(Args...) ):m_t(t),m_f(f) {} 
  5.     R operator()(Args... args) 
  6.     { 
  7.         return (m_t->*m_f)(args ...); 
  8.     } 
  9.     //R operator()(Args&&... args)  
  10.     //{ 
  11.             //return (m_t->*m_f)(std::forward(args) ...); 
  12.     //} 
  13.  
  14. private: 
  15.     T* m_t; 
  16.     R  (T::*m_f)(Args...); 
  17. };    
  18.  
  19. template  
  20. MyDelegate CreateDelegate(T* t, R (T::*f)(Args...)) 
  21.     return MyDelegate(t, f); 
  22.  
  23. struct A 
  24.     void Fun(int i){cout<
  25.     void Fun1(int i, double j){cout<
  26. }; 
  27.  
  28. int main() 
  29.     A a; 
  30.     auto d = CreateDelegate(&a, &A::Fun); //創(chuàng)建委托 
  31.     d(1); //調(diào)用委托,將輸出1 
  32.     auto d1 = CreateDelegate(&a, &A::Fun1); //創(chuàng)建委托 
  33.     d1(1, 2.5); //調(diào)用委托,將輸出3.5 

本文題目:可能學(xué)了假的編程?C++新標準難點解析之可變模板參數(shù)
文章地址:
http://m.5511xx.com/article/djgsehp.html