模板元编程(1):完美转发和变长模板

#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;
}

这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值