C++模板 - traits & policy

traits和policy在泛型编程里面还是挺常见的。像stl的string实现里面就用到了traits,boost里面也很多地方用到traits。

traits和policy很多时候都会一起使用,让我们在泛型编程里面多了一些思路。

traits:中文解释为特征,记得候捷在《stl源码剖析》那本书里面还叫做萃取什么的。当我们想从一个类型身上获取他的一个附加特性的时候,往往可以考虑traits。比方说有一个类型T, 对他进行一些操作,然后要返回一个类型,那么可以理解为一个返回类型是跟T相关的。还有比如给定一个迭代器,想从迭代器上获取相关的容器类型什么。这个都是type traits的典型应用,至于value traits,很多时候是在一个traits里面给类型附加一个初始化值。经常可以看到一个tratis类里面有一个类型定义和一个相应的初始化(静态常量或者一个静态函数)。类似:

template<>
struct traits<int>
{
	typedef double AccuT;
	static AccuT Zero(){ return 0.0; };
};

policy:中文解释为策略。在泛型编程里面,如果某些行为代码可能会变化,那么往往可以使用policy。通过使用不同的policy可以改变一个模板函数的行为。比如下面的代码:

template<class T, class P>
typename traits<T>::AccuT accum(const T* ptr, int len)
{
	traits<T>::AccuT total = traits<T>::Zero();

	for (int i = 0; i < len; i++)
	{
		P::accumulate(total, *(ptr + i));
	}

	return total;
}

如果累加算法可能会变,那么我们就可以通过传入一个模板类,通过这个类的成员函数来实现不同的算法。

traits和policy拓展了我们的视野,让我们多了一些思路。但是也不要一味的滥用(就像设计模式一样,有些时候过度设计还不如没有设计)。

stl的accumulate函数就没有使用traits和policy。看下面的代码:

template<class _InIt,
	class _Ty> inline
	_Ty accumulate(_InIt _First, _InIt _Last, _Ty _Val)
	{	// return sum of _Val and all in [_First, _Last)
	_DEBUG_RANGE(_First, _Last);
	return (_Accumulate(_Unchecked(_First), _Unchecked(_Last), _Val));
	}
template<class _InIt,
	class _Ty,
	class _Fn2> inline
	_Ty accumulate(_InIt _First, _InIt _Last, _Ty _Val, _Fn2 _Func)
	{	// return sum of _Val and all in [_First, _Last), using _Func
	_DEBUG_RANGE(_First, _Last);
	_DEBUG_POINTER(_Func);
	return (_Accumulate(_Unchecked(_First), _Unchecked(_Last), _Val, _Func));
	}

std::accumulate()的返回值类型其实是通过一个模板参数传进去的_Ty _Val。行为函数也是通过一个模板参数穿进去的_Fn2 _Func。

个人感觉每种方案都有自己的优缺点,还是那句话,在合适的场合使用合适的解决方案。方案本身没有绝对的好和不好,只有合适的方案没有最好的方案(只有最强的玩家没有最强的职业)

traits的原作者Nathan有句话:traits是一种替代模板参数的方案。但是他并没有说模板参数不好,或者traits比模板参数好多少。

时间: 2024-10-12 10:13:25

C++模板 - traits & policy的相关文章

【C++模版之旅】项目中一次活用C++模板(traits)的经历 -新注解

问题与需求: 请读者先看这篇文章,[C++模版之旅]项目中一次活用C++模板(traits)的经历. 对于此篇文章提出的问题,我给出一个新的思路. talking is cheap,show me the code. 代码: class ExportData { union { string * sp; long* lp; double* dp; void* vp; }; enum my_type {SP,LP,DP} types; static unordered_map<type_index

【C++模版之旅】项目中一次活用C++模板(traits)的经历

曾经曾在一个项目中碰到过一个挺简单的问题,但一时又不能用普通常规的方法去非常好的解决,最后通过C++模板的活用,通过traits相对照较巧妙的攻克了这个问题.本文主要想重现问题发生,若干解决方式的比較,以及最后怎样去解决的过程,或许终于的方案也并非最好的方案,但至少个人认为从发现到思考到解决到改善,这是一个对帮助个人成长非常不错的过程,所以凭记忆想把它记录下来,分享给大家. 先描写叙述下问题,项目中有这样一个接口类会暴露给外部使用,接口类定义例如以下(类方法名称以及描写叙述该问题无关的内容会有所

C++模板 - traits

traits是个很好玩的东西,在泛型编程里面很常见.最早出于老外的一篇论文.http://www.cantrip.org/traits.html?seenIEPage=1 建议仔细阅读. 首先我们来看一段代码. template<class T> T accum(const T* ptr, int len) { T total = T(); for (int i = 0; i < len; i++) { total += *(ptr + i); } return total; } 这是个

【C++】Geekband-专题四:traints的使用

1. 基本定义2. Fixed Traits2.1 传统方法2.2 使用Traits方法2.3 总结3. Value Traits4. Parameterized TraitsReference 1. 基本定义 Think of a trait as a small object whose main purpose is to carry information used by another object or algorithm to determine "policy" or

转 一个典型的 C++ 程序员成长经历:

1.  完整的学一遍 C++ 所有语言特性,典型书籍 "The C++ Programming Language" Part1, Part2, "C++ Primer" 感觉 C++ 像大杂烩(多编程范型),各种精妙的语法特性 (friend, virtual/RTTI, const/mutable, exception, template),太多精妙的东西容易导致记忆琐碎化,学了又忘了,尤其是那些很少用的部分 实践:编写一些带 class 和 virtual 字眼

C++设计新思维

问题与需求: 请读者先看这篇文章,[C++模版之旅]项目中一次活用C++模板(traits)的经历. 对于此篇文章提出的问题,我给出一个新的思路. talking is cheap,show me the code.文章名字很大,仅仅是为了引起你的注意. 代码: class ExportData { union { string * sp; long* lp; double* dp; void* vp; }; enum my_type {SP,LP,DP} types; static unord

Kubernetes NetworkPolicy工作原理浅析

Kubernetes能够把集群中不同Node节点上的Pod连接起来,并且默认情况下,每个Pod之间是可以相互访问的.但在某些场景中,不同的Pod不应该互通,这个时候就需要进行访问控制.那么如何实现呢? 简介 ??Kubernetes提供了NetworkPolicy的Feature,支持按Namespace和按Pod级别的网络访问控制.它利用label指定namespaces或pod,底层用iptables实现.这篇文章简单介绍Kubernetes NetworkPolicy在Calico上的工作

C++模板 - policy类

一讲到traits,相应的就会联系到policy.那么policy是干啥的呢? 看一下下面的累加代码. template<class T, class P> typename traits<T>::AccuT accum(const T* ptr, int len) { traits<T>::AccuT total = traits<T>::Zero(); for (int i = 0; i < len; i++) { total += *(ptr +

模板拾遗二_traits和policy

1,traits char name[] = "templates"; int legnth = sizeof(name) - 1; accum(&name[0], &name[legnth]); 2,value trait value trait有个缺点:在所在类的内部,C++只允许对整形和枚举类型初始化成静态成员变量.显然folat或其它自定义类型等不能使用上面解决方案. 3,使用静态成员函数来做为value trait 4,trait提供了一种配置具体元素(通常是