深入理解C++11(二十)

深入理解C++11(二十)

可变参数模板消除重复代码
可变参数模板的一个特性是参数包中的模板参数可以是任意数量和任意类型的,因此,可以以一种更加泛化的方式去处理一些问题,比如一个泛型的打印函数,在C++11之前,要写一个通用的打印函数可能不得不像代码清单3-3这样写。

template<typename T>
void Print(T t)
{
cout<<t<<endl;
}
template<typename T1, typename T2>
void Print(T1 t1, T2 t2)
{
cout<<t1<<t2<<endl;
}
template<typename T1, typename T2, typename T3>
void Print(T1 t1, T2 t2, T3 t3)
{
cout<<t1<<t2<<t3<<endl;
}
template<typename T1, typename T2, typename T3, typename T4>
void Print(T1 t1, T2 t2, T3 t3, T4 t4)
{
cout<<t1<<t2<<t3<<t4<<endl;
}
template<typename T1, typename T2, typename T3, typename T4, typename T5>
void Print(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
{
cout<<t1<<t2<<t3<<t4<<t5<<endl;
}

可以看到这个Print函数最多只能支持5个模板参数的打印,而且很多重复的模板定义,当需要打印更多的参数时不得不再增加模板定义,当然可以通过一些宏手段消除这种重复,但这又带来难于调试以及代码可读性变差的问题。通过可变参数模板可以完全消除这种重复,代码简洁而优雅,如下:

template<typename T>
void Print(T t)
{
cout<<t<<endl;
}
template<typename T, typename... Args>
void Print(T t, Args... args)
{
cout<<t;
Print(args...);
}

在C++11之前写一个对象创建的工厂函数,也需要写很多重复的模板定义,如代码清单3-4所示

template<typename T>
T* Instance()
{
return new T();
}
template<typename T, typename T0>
T* Instance(T0 arg0)
{
return new T(arg0);
}
template<typename T, typename T0, typename T1>
T* Instance(T0 arg0, T1 arg1)
{
return new T(arg0, arg1);
}
template<typename T, typename T0, typename T1, typename T2>
T* Instance(T0 arg0, T1 arg1, T2 arg2)
{
return new T(arg0, arg1, arg2);
}
template<typename T, typename T0, typename T1, typename T2, typename T3>
T* Instance(T0 arg0, T1 arg1, T2 arg2, T3 arg3)
{
return new T(arg0, arg1, arg2, arg3);
}
template<typename T, typename T0, typename T1, typename T2, typename T3, typename
T4>
T* Instance(T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
{
return new T(arg0, arg1, arg2, arg3, arg4);
}
struct A
{
A(int){}
};
struct B
{
B(int,double){}
};
A* pa = Instance<A>(1);
B* pb = Instance<B>(1,2);

可以看到一样的问题,存在大量的重复的模板定义以及限定的模板参数。用可变模板参数可以消除重复,同时去掉参数个数的限制,代码很简洁,通过可变参数模版优化后的工厂函数如下:

template<typename... Args>
T* Instance(Args... args)
{
return new T(args...);
}
A* pa = Instance<A>(1);
B* pb = Instance<B>(1,2);

在上面的实现代码T*Instance(Args…args)中,Args是值拷贝的,存在性能损耗,可以通过完美转发来消除损耗(关于完美转发,读者可以参考第2章的内容介绍),代码如下:

template<typename... Args>
T* Instance(Args&&... args)
{
return new T(std::forward<Args >(args)...);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值