#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.youkuaiyun.com/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;
}