成免费的crm,久久国产精品新农夫导航新妓网,恋夜秀场全部视频安卓手机,女校花强奷在线播放A级

C++?折疊參數包詳解(悄然增強編程效率)

c++?折疊參數包詳解(悄然增強編程效率)

 

前言

本節將為大家帶來折疊參數包的詳細講解,折疊參數包為c++模板編程提供了更加靈活和強大的工具,可以提高代碼的簡潔性和可讀性,看完后希望對你有收獲

 

一、介紹

折疊參數就是一個參數包, 代表是多個未知,tuple元組就是一個折疊參數的使用

折疊參數類型:

  • typename ...args: args參數包的包名 ,本質是聲明一個args折疊參數類型
  • args ...arg: 折疊參數包類型的變量
  • ...:理解為多個意思

 

二、函數模板中使用折疊參數

1、遞歸方式展開

遞歸方式的展開是比較好理解的,每一次調用第二個print函數就打印一次data,然后又調用自己,這時候參數包也剝離了一個參數,也就是調用自己會打印下一個data

有的同學看了下面的代碼可能會疑惑,為什么會有兩個函數,這是因為上面的函數為終止函數,也就是當第二個函數參數包中只有一個參數時調用第一個函數

template <typename _ty>
void print(_ty data) 
{
	cout << data << endl;
}
template <typename _ty,typename ...args>
void print(_ty data, args ...args) 
{
	cout << data << "\t";
	print(args...);
}

2、列表數據展開

這個的難點和重點在于initializer_list<int>{(printdata(args), 0)...};,這一行代碼用到了列表和逗號表達式的特性,不用說列表的每個值最后都被初始化為0,但是列表的每個值被初始化為0的時候,他們會先執行printdata(args(n)),也就是會不斷打印,參數包不斷展開

template <typename _ty>
void printdata(_ty data) {
	cout << data << "\t";
}
template <typename ...args>
void printargs(args ...args)
{
	initializer_list<int>{(printdata(args), 0)...};
	cout << endl;
}

3、完美轉發的方式展開

完美轉發一般是用來統一接口,也就是有許多函數,他們的參數數量、類型不同,我們把他們統一為只用函數名就可以調用該函數,且不減少其原功能

這里我們用仿函數接收一下用bind綁定的函數以及參數包,注意這里函數和參數包綁定的時候都用了完美轉發

什么是完美轉發吶?forword是為了解決在函數模板中,使用右值引用參數(t&&),傳遞右值進去以后,類型會變為左值的問題。當傳入的參數是一個對象時,右值變左值就會出問題,因為左值調用拷貝構造,右值調用移動構造。本來可以用移動構造提高效率,卻因為右值變成左值,調用了拷貝構造。所以我們要把它變回去!實參傳的是右值,進入函數體還是右值,這就是完美轉發

class test 
{
public:
	void printk() 
	{
		if (func) func();
	}
	template <typename func,typename ...args>
	void connect(func&& f, args&& ...args)    //右值引用
	{
		func = bind(forward<func>(f), forward<args>(args)...);
	}
protected:
	function<void()> func;
};
void sum(int a, int b) 
{
	cout<< a + b;
}
int main() 
{
	test test;
	test.connect(sum, 1, 2);
	test.printk();
	test.connect([](int a, int b) {cout << endl << a + b; }, 3, 8);
	test.printk();
	return 0;
}

上面的例子中通過connect綁定函數和參數包,實現統一接口的功能,通過printk函數調用

 

三、類模板中使用折疊參數

1、繼承+模板特化的方式展開

類中實現折疊參數,前兩個類是必須,對應上面的終止函數,繼承的時候要寫清楚public test<args...>,還有就是第三個類必須要一個無參構造函數,且帶參數包的的構造函數初始化時要調用子類的構造函數,還有就是打印的時候要一層一層的,采用繼承+模板特化就是一代一代的

template <typename ...args>
class test;
template<>
class test<> {};
template <typename _ty, typename ...args>
class test<_ty, args...> :public test<args...>
{
public:
	test() {}
	test(_ty data, args ...args) :data(data), test<args...>(args...) {}
	test<args...>& getobject() { return *this; }
	_ty& getdata() { return data; }
protected:
	_ty data;
};
void testone() 
{
	test<string, int, double> test("fsdjf", 32, 3.23);
	cout << test.getdata() << "\t" << test.getobject().getdata() << "\t" << test.getobject().getobject().getdata() << endl;
}

2、遞歸的方式展開

遞歸這一種就是把自己當對象調用,其它的和上面相同

template <typename ...args>
class my_tuple;
template<>
class my_tuple<> {};
template <typename _ty, typename ...args>
class my_tuple<_ty, args...>
{
public:
	my_tuple() {}
	my_tuple(_ty data, args ...args) :data(data),args(args...) {}
	_ty& getdata() { return data; }
	my_tuple<args...>& getobject() { return *this; }
protected:
	_ty data;
	my_tuple<args...> args;
};
void testtwo() 
{
	test<string, int, double> test("fsdjf", 32, 3.23);
	cout << test.getdata() << "\t" << test.getobject().getdata() << "\t" << test.getobject().getobject().getdata() << endl;
}

關于c++折疊參數包悄然增強編程效率的文章就介紹至此,更多相關c++折疊參數包內容請搜索碩編程以前的文章,希望以后支持碩編程

下一節:c語言怎么解決qstring與qbytearray互相轉換的問題

c語言編程技術

相關文章