policy和trait的差别
来源:互联网 发布:制相册的软件 编辑:程序博客网 时间:2024/05/02 13:36
policy和trait都是在模板库设计时的常用技术,根据牛津字典:
trait:用来刻画一个事物的特性。
policy:为了某种有益或有利的目的而采取的一系列动作。
按照《Modern C++ Design》,policy着重于行为,而trait更关注于类型。
下面分别介绍。
1 trait简介
trait技术是一种古老的编程技术,该技术主要用于模板库的设计。实际上,trait技术是设计STL的基础。
引入trait技术的第一人,Nathan Myers给出一个更加开放的定义:
trait class:是一种用于代替模板参数的类。作为一个类,它可以包括有用的类型,也可以包括常量;作为一个模板,它提供一种实现“额外层次间接性”的途径,而正是这种额外层次间接性“解决了所有的软件问题。
trait主要利用了C++模板语法的局部特化和完全特化得以实现。
考虑一个简单的例子,假设我们要实现一个累加运算的类,为了适用多种型别,我们将其泛化为一个模板类:
template <typename T>
class Accum
{
public:
static T accum (T const* beg, T const* end)
{
T total = T();
while (beg != end)
{
total += *beg;
++beg;
}
return total;
}
};
这段代码至少存在两个问题:
l 零值问题,如何为一个类型生成一个0值,对于内建数值类型,T()通常可以符合要求;
l 数值溢出问题,对于求和的结果,我们定义为类型T,但有可能产生数值的溢出,比如两个char值的求和结果就可能无法用char来容纳,可能需要一个int类型的值才能保存求和结果。
那为了解决这个问题,我们可以采用C++模板中局部特化或者完全特化的技术,对于特殊型别特殊处理,比如,我们可以添加如下代码:
template <>
class Accum<char>
{
public:
static int accum (char const* beg, char const* end)
{
int total = 0;
while (beg != end)
{
total += *beg;
++beg;
}
return total;
}
};
这样做当然是可以的,但是会很麻烦,因为我们对于每一种需要特殊处理的型别,都要重写一遍accum函数,完全特化或者局部特化的代价比较大。
为了解决这个问题,并且减少局部特化或者全局特化的代价,我们需要定义一个轻量级的类,这个类相当于一个中间层,为我们提供了类型到类型的映射。这样一旦引入特殊类型,我们只要添加这个类的局部特化或者完全特化版本,就可以满足新的需求,而无需修改Accum类。这个轻量级的类,我们就称之为trait类。
trait类的具体代码如下:
template<typename T>
class AccumulationTraits {
public:
typedef T AccT;
static AccT zero() {
return T();
}
};
template<>
class AccumulationTraits<char> {
public:
typedef int AccT;
static AccT zero() {
return 0;
}
};
template<>
class AccumulationTraits<short> {
public:
typedef int AccT;
static AccT zero() {
return 0;
}
};
template<>
class AccumulationTraits<int> {
public:
typedef long AccT;
static AccT zero() {
return 0;
}
};
template<>
class AccumulationTraits<unsigned int> {
public:
typedef unsigned long AccT;
static AccT zero() {
return 0;
}
};
template<>
class AccumulationTraits<float> {
public:
typedef double AccT;
static AccT zero() {
return 0;
}
};
然后,我们对Accum类添加一个模板参数,用于表示所使用的trait类:
template < typename T,
typename AT = AccumulationTraits<T> >
class Accum {
public:
static typename AT::AccT accum (T const* beg, T const* end) {
typename AT::AccT total = AT::zero();
while (beg != end) {
total += *beg;
++beg;
}
return total;
}
};
2policy简介
policy技术来源于《Modern C++ Design》,此技术是把C++模板语法和C++的多重继承语法结合在一起所形成的设计方法。policy技术符合开放封闭原则和单一职责原则。
policy技术要求把一个模板类分解成多个policy class,每一个policy class表示一个单一职责的类,代表一个模板参数,policy class之间要求是彼此正交的。然后通过多重继承的方式使每个policy class都是该模板类的基类(这个不是必须的)。
比如:
template class Compition <typename policyA,
typename policyB,
typename policyC
>
: public policyA, policyB, policyC
{
...
};
要求policy class之间彼此正交并不困难,只要设计时确保policy class的接口之间没有调用关系就可以了。如果policy class之间是耦合的,那说明它们之间并非正交,那这样的设计也是不正确的。
通过使用policy技术,设计出的类会有足够的弹性,因为替换不同的policy会达到不同的效果,但policy class的确定需要在编译时,如果我们需要在运行时决定使用何种policy class,则这种设计方法并不适用。
在上一节trait的例子中,我们把累积和求和等价起来了。实际上还有其他种类的累积。以下是运用policy的一个例子:
template < typename T,
typename Policy = SumPolicy,
typename AT = AccumulationTraits<T> >
class Accum {
public:
static typename AT::AccT accum (T const* beg, T const* end) {
typename AT::AccT total = AT::zero();
while (beg != end) {
Policy::accumalate(total, *beg);
++beg;
}
return total;
}
};
SumPolicy类可以编写如下:
class SumPolicy {
public:
template<typename T1, typename T2>
static void accumulate (T1& total, T2 const& value) {
total += value;
}
};
在这个例子中,我们把policy实现为一个具有一个成员函数模板的普通类。如果我们要换一种算法,例如让累积变成求积而不是求和,可以编写一个新的policy类:
class MultPolicy {
public:
template<typename T1, typename T2>
static void accumulate (T1& total, T2 const& value) {
total *= value;
}
};
只要在使用累积时,更换模板参数就可以更改求累积的算法,但这需要在编译时完成。
参考文献:
1 《C++设计新思维——泛型编程与设计模式之应用》(Modern C++ Design ——Generic Programming and Design Patterns Applied)
2 《C++ Templates中文版》(C++ Templates The Complete Guide)
- policy和trait的差别
- trait和policy研习
- 详述trait和policy演化
- 详述trait和policy演化
- 模板特性(trait)和政策(policy)
- c++ template(9)trait和Policy
- 我的C++实践(4):trait与policy模板技术
- 我的C++实践(4):trait与policy模板技术
- trait与policy模板技术
- C++ Templates:trait与policy类
- Scala 的Trait和类型转换
- PHP的类和对象(七)Trait
- scala class和object,trait的区别
- trait的基本声明和使用
- 增强学习中的on-policy和off-policy的区别
- 增强学习中的on-policy和off-policy的区别
- 我的C++实践(4):trait与policy模板技术http://blog.csdn.net/zhoudaxia/article/details/4486487
- 泛型程序设计之 Trait 与 Policy 技巧初探
- jQuery对checkbox的操作
- .Net framework初始化错误
- 类加载来源
- POJ 3510 string
- 计算机相关国际会议排名
- policy和trait的差别
- 实战搭建Gearman 分布式处理框架 + python客户端
- linux下vi中批量删除空行的方法:
- SAS9.1.3安装过程中反复出现重启动挂起的解决方案
- 关于数据表映射在更新时候出现的一些问题
- 求字符串最长对称字符串的长度(转何海涛博客)
- HTTP与HTTPS的区别
- 用类实现链表
- Linux 软件安装使用(7)根目录的简介