变长参数模板

#include "stdafx.h"
#include "stdarg.h" 

#include <iostream>
#include <functional>
#include <vector>

using namespace std;

/************************************************************************/
/* Title: 变长参数模板 示例                                              */
/* Environment:VS2013Update4                                           */
/* Author: kagula                                                       */
/* Keyword: Variadic templates, Parameter pack, extension pack          */
/* Date: 2015-07-20                                                     */
/* Remark:参考资料不够准确,在它基础上对样本做了修改                       */
/* Reference: 《C 可变长参数 VS C++11 可变长模板》                        */
/*             http://blog.csdn.net/zj510/article/details/36633603      */
/************************************************************************/

double Sum(int count, ...)
{
	va_list ap;//need include stdarg.h file
	double sum = 0;

	va_start(ap, count);

	for (int i = 0; i < count; ++i)
	{
		double arg = va_arg(ap, double);
		sum += arg;
	}

	va_end(ap);

	return sum;
}

//////////////////////////////////////////////////////////////////////////
// parameter pack 使用方式一
// Variadic template 代表了 零个或多个template
// Variadic template 的定义 typename...
// Variadic template 的“变量” Tail...
// 下面是第一个例子
//////////////////////////////////////////////////////////////////////////
template<typename... A> class BMW{}; // 边界

template<typename First, typename... Args>
class BMW<First, Args...> : public BMW < Args... >
{
public:
	BMW()
	{
		printf("type: %s\n", typeid(First).name());
	}
private:
	First head;
};


BMW<int, char, float> car;

//////////////////////////////////////////////////////////////////////////
// parameter pack 使用方式二
//////////////////////////////////////////////////////////////////////////
template<typename... T> double Sum2(T... first)  // 边界
{
	return 0;
}

template<typename T, typename... Args> double Sum2(T first, Args... arg)
{
	double ret = first + Sum2(arg...);

	return ret;
}

//////////////////////////////////////////////////////////////////////////
// parameter pack 使用方式二的变形
//////////////////////////////////////////////////////////////////////////
template<typename T> T Sum3(T v) {
	return v;
}

template<typename T, typename... Args> T Sum3(T first, Args... args) {
	return first + Sum3(args...);
}

//////////////////////////////////////////////////////////////////////////
// parameter pack 在 lambda 中的应用
// lambda 同 std::function是两种不同的类型。
// 所以下面是 lambda 转 std::function 的示例。
//////////////////////////////////////////////////////////////////////////
template <typename T>
struct function_traits
	: public function_traits < decltype(&T::operator()) >
{};

template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits < ReturnType(ClassType::*)(Args...) const > {
	typedef function<ReturnType(Args...)> f_type;
};

template <typename L>
typename function_traits<L>::f_type make_function(L l){
	return (typename function_traits<L>::f_type)(l);
}

template <typename A, typename B>
vector<B> map(std::function<B(A)> f, vector<A> arr) {
	vector<B> res;
	for (size_t i = 0; i < arr.size(); i++) res.push_back(f(arr[i]));
	return res;
}

int _tmain(int argc, _TCHAR* argv[])
{
	//
	double sum = Sum(4, 1.0, 2.0, 3.0, 4.0);

	cout << "C Syntax: " << sum << endl;

	//
	double ret2 = Sum2(1.0, 2.0, 3.0, 4.0);
	cout << "C++11 Syntax: " << ret2 << endl;

	//
	double ret3 = Sum3(1.0, 2.0, 3.0, 4.0);
	cout << "C++11 Syntax2: " << ret3 << endl;

	//下面这段代码,只是演示 variadic template with lambda
	//实践上,更适合用C++ GPU技术来处理
	vector<int> a = { 1, 2, 3 };
	vector<int> result = map(make_function([](int x) -> int { return x*x; }), a);
	for each (auto var in result)
	{
		cout << var << endl;
	}

	//
	cin.get();

	return 0;
}



你可能感兴趣的:(变长参数模板)