模板元编程(1):完美转发和变长模板
2018-02-28 18:57
218 查看
#include <iostream> #include <typeinfo> #include <type_traits> using namespace std; struct A { A() {} A(const A& a) { cout << "Copy Constructed " << __func__ << endl; } A(A&& a) { cout << "Move Constructed " << __func__ << endl; } }; struct B { B() {} B(const B& b) { cout << "Copy Constructed " << __func__ << endl; } B(B&& b) { cout << "Move Constructed " << __func__ << endl; } }; template <typename... T> struct MultiTypes; //先声明变长结构体模板的存在 template <typename T1, typename... T> struct MultiTypes<T1, T...> : public MultiTypes<T...> { T1 t1; MultiTypes<T1, T...>(T1 a, T... b) : t1(a), MultiTypes<T...>(b...) { cout << "get inside " << __func__ << endl; cout << "MultiTypes<T1, T...>(T1 a, T... b)" << endl; } }; //全特化,并且是变长参数包递归的出口 template<> struct MultiTypes<> { MultiTypes<>() { cout << "get inside final MultiTypes()"<< endl; cout << "MultiTypes<>()" << endl; } }; //完美转发的变长模板,该转发函数的模板形参包含一个变长模板 template <template <typename...> class VariadicType, typename... Args> VariadicType<Args...> Build(Args&&... args) //Args&&...这种解包方式,将会把每一个arg_n变成Argn&&,引用折叠规则 { cout << "get inside " << __func__ << endl; return VariadicType<Args...>(forward<Args>(args)...); } template <template <typename...> class VariadicType, typename... Args> VariadicType<Args...> NewBuild(Args... args) //取消完美转发的&&解包方式,来看看情况 { cout << "get inside " << __func__ << endl; return VariadicType<Args...>(forward<Args>(args)...); } int main() { A a; B b; /***** 采用完美转发的方式来调用 ****/ cout << typeid(Build<MultiTypes>(a, b)).name() << endl; //采用了模板参数自动推导,而返回值类型必须显式实例化 MultiTypes<A&, B&> c = Build<MultiTypes>(a, b); cout << typeid(c.t1).name() << endl; //因为Arg&&这种完美转发的引用折叠使用,导致了实际的返回值类型 //不是MultiTypes<A, B>,而是MultiTypes<A&, B&>,这直接导致MultiTypes内的t1类型并非A或B,而是结构体引用类型A&, //这也是为什么在MultiTypes内部并没有出现调用A或B的拷贝构造或移动构造函数的原因,而是直接调用了=赋值符号即可 MultiTypes<A, B> d = NewBuild<MultiTypes>(a, b); //应该会触发拷贝构造函数的调用 /** 1. a/b --> NewBuild<MultiTypes>(a, b); 形参拷贝赋值,对应第一次的A B拷贝 2. NewBuild<MultiTypes>(a, b) --> return VariadicType<Args...>(forward<Args>(args)...); 模板函数内部,由于实例化时不具名形参作为右值,对应第一组的移动构造 3. MultiTypes<A,B>(a,b): t1(a),MultiTypes<B>(b) 4. MultiTypes<B>(b):t1(b), MultiTypes<>() **/ return 0; }
相关文章推荐
- C++模板(4) - 模板元编程
- Effective C++第七章-模板和泛型编程之traits和TMP(模板元编程)
- 用VS 2015写C++代码:体验一下变参模板、完美转发和lambda
- C++之:模板元编程(三) 默认模板参数
- 模板--模板元编程
- 深入理解模板 模板元编程
- 转发:在ASP.NET MVC中引入 后台模板ACE Bootstrap
- linux网络设备应用与驱动编程学习4——模板与实例(A)
- JQuery FlexiGrid的asp.net完美解决方案-dotNetFlexGrid使用指南(二)服务端查询、快速查询和Html模板
- 关于模板元编程的一点反思
- C++ Primer 第十六章 模板与范型编程
- windows下,C++实现串口编程,串间口转发数据
- (原创)C++11改进我们的程序之move和完美转发
- 模板元编程-C++
- 《C++0x漫谈》系列之:右值引用(或“move语意与完美转发”)(上)
- 《C++0x漫谈》系列之:右值引用(或“move语意与完美转发”)(下)
- 常用python编程模板汇总
- 第16课 右值引用(3)_std::forward与完美转发
- Linux input子系统编程、分析与模板
- 斐波那契函数再总结--模板元编程