您的位置:首页 > 其它

模板的应用: 判断类型选择合适的传参方式 以提高效率

2017-01-23 11:34 309 查看
 一、需求引入

我们都知道,对于一个很大的数据结构而言,采用传值的方式通常是很耗费资源的,因此对于这种数据结构,应该“传const 引用”(或者在C中传递const指针);相反,对于更小的数据结构,情况并非这么简单:通常依赖于实际的代码体系结构,总的来说小的数据结构究竟采取何种传递方式,对性能影响并不大,但是也必须小心处理

二、实现方式

面对   templates,事情变得更为棘手。我们不知道将被用来替换   template parameters 的那个type  到底有多大。此外,最终决定也不仅仅取决于大小:一个伴有「代价高昂之 copy  构造函数」的小  型结构可能会让你醒悟:以  by reference-to-const 传递惟读参数还是比较有道理的。

第一步(第一种方式):根据type的大小选择合适的传参方式

这里我们举个例子:对于不大于2个指针大小的类型,基本模板将采用传值的方式传递参数,而对于其他的类型,将采用传递const引用的方式传递参数

这就让我们联想到了在前一篇博客中提到的IfThenElse模板了

template<typename T> 

class RParam { 

public: 

typedef typename IfThenElse<sizeof(T)<=2*sizeof(void*), 

T, 

T const&>::ResultT Type; 

};

第二步:即使数据类型很小,也可能涉及昂贵的拷贝构造函数,因此需要编写很多全特化和局部特化

这里以Array<T>的局部特化为例:当参数是Array<T>类型的容器时,采用传递const引用的方式

template<typename T> 

class RParam<Array<T> > { 

public: 

typedef Array<T> const& Type; 

};

...

第三步(第二种方式):上面是对class类型的处理,下面我们希望在基本模板中能对非class类型以传值的方式调用,另外对于某些对性能要求比较苛刻的class类型,我们有选择的添加这些类为“传值”的方式

这让我们联想到了前面一篇博客提到的IsClassT<T> 模板 来鉴定参数是否为class types类型

template<typename T> 

class RParam { 

public: 

typedef  typename  IfThenElse<IsClassT<T>::No, 

T, 

T const&>::ResultT Type; 

}

第四步:假设我们手里有2个具体类

class MyClass1 { 

public: 

MyClass1 () { 



MyClass1 (MyClass1 const&) { 

std::cout << "MyClass1 copy constructor called\n"; 



}; 

 

class MyClass2 { 

public: 

MyClass2 () { 

}  

MyClass2 (MyClass2 const&) { 

std::cout << "MyClass2 copy constructor called\n"; 



}; 

第五步:针对MyClass2 objects  将以  by value 方式传递 

//全特化

template<> 

class RParam<MyClass2> { 

public: 

typedef MyClass2 Type; 

}; 

第六步:调用上面的模板,采用内联方式可以实现模板实参的推导

//以下函数允许参数以  by value  或  by reference  方式传递 

template <typename T1, typename T2> 

void foo_core (typename RParam<T1>::Type p1, typename RParam<T2>::Type p2) { 

//... 



 

//下面是个  wrapper,用以免除(显式)指定  template parameter的责任 

template <typename T1, typename T2> 

inline 

void foo (T1 const & p1, T2 const & p2) { 

foo_core<T1,T2>(p1,p2); 



三、使用模板

int main() { 

MyClass1 

mc1; 

MyClass2 

mc2; 

foo(mc1,mc2);   //  此式效果相当于  foo_core<MyClass1,MyClass2>(mc1,mc2) 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: