traits编程技法感悟

转载 2016年06月01日 09:48:07

转载自 镜中影的技术博客 
本文链接地址: traits编程技法感悟) 
URL:http://blog.csdn.net/linkpark1904/article/details/50790917

由于工作学习需要,在研究生阶段主要编程语言还是以C++为主,多少在学习语言的过程中,道听途说c++很高大上,c++是一门四不像的语言,c++学起来很难,用c++做工程的不多等等这之类的话。于一门语言来说,c++确实算的上历史悠久,众人对其评价也是褒贬不一。无论如何,在我看来,一门语言能存活至今,肯定有其存在的价值和意义,也有许多值得我们学习的地方。

近来有幸拜读《STL源码剖析》,膜拜一下设计标准C++库的大神们是怎样用C++来绘制出STL这个庞大壮丽的王国。

书中偶然发现STL中是如何设计迭代器(所谓迭代器,本质上就是通用智能指针)的,书中提及到一种Traits编程技法,感觉很新奇。所谓Traits编程技法,目的是为了弥补C++没有typeof()调用的缺陷。在脚本语言(javascript,python……)中,变量的类型往往可以通过typeof调用获取,而在C++中这是没法做到的,所以才会采用一些特殊的办法去弥补这一点。

回归正题,倘若让你设计一个通用的迭代器,以及一个能打印任何通用迭代器的值得模板函数,你会怎么设计?所谓指针无非是提供*操作(暂时不考虑指针的++,–操作)。所以第一款自定义迭代器的设计如下所示:

template <class T>
class MyIter{
public:
    typedef T value_type;
    T *ptr;
    MyIter(T *p = 0):ptr(p){}
    T& operator*()const{return *ptr;}
};

其中利用typedef T value_type把模板类型T暴露出来。这个指针类,提供了构造函数,重载了*操作符,如何设计打印通用迭代器值得函数呢?这个函数的返回值又怎么来定?正确的做法如下:

template <class I>
typename I::value_type
func(I iter){ return *iter; }

其中,模板I必须为提供value_type变量的自定义迭代器,编译器在编译阶段,会通过MyIter的实际模板值推导出func函数的返回值类型应该是什么,这样func函数的返回值就可以随着我们自定义迭代器传入的模板参数的改变而改变。说白了,如果我们给MyIter传入一个int型,那么由于typedef T value_type的作用,导致value_type为int,所以func的返回值为int,整体的可执行代码如下:

#include <iostream>
using namespace std;

template <class T>
class MyIter{
public:
    typedef T value_type;
    T *ptr;
    MyIter(T *p = 0):ptr(p){}
    T& operator*()const{return *ptr;}
};

template <class I>
typename I::value_type
func(I iter){
    return *iter;
}

int main(){
    MyIter<int> myIter(new int(4));
    cout << func(myIter) <<endl;

    return 0;
}

不要以为这样就完美了,这里我们的func函数只能支持我们自定义的迭代器,也就是迭代器中自定义value_type那么对于一个通用指针如何进行支持呢,例如func(new int(4))这样的调用,为了让函数好用,做到极致就需要函数能够适配多种多样的情况。为此才会引申出我们的Traits编程技法。利用模板的特化(有点像函数的重载)特性,在中间增加一层Traits类,让我们设计的func函数既支持自定义的迭代器又支持通用指针。具体代码如下所示:

#include <iostream>

using namespace std;

//自定义迭代器
template <class T>
struct MyIter{
    typedef T value_type;
    T *ptr;
    MyIter(T* p = 0):ptr(p){}
    T& operator*() const{ return *ptr;}
};

//Traits编程技法
//支持自定义迭代器
template <class T>
class Traits{
public:
    typedef typename T::value_type value_type;
};

//特化,支持传统通用指针
template <class T>
class Traits<T*>{
public:
    typedef T value_type;
};

//特化,支持传统const指针
template <class T>
class Traits<const T*>{
public:
    typedef T value_type;
};

//模板函数
template <class I>
typename Traits<I>::value_type
func(I iter){
    return *iter;
}


int main(){
    MyIter< int > p(new int(8));
    const char *ptr = "abce";
    int *a = new int(9);
    cout << func(p) <<endl;
    cout << func(a) <<endl;
    cout << func(ptr) << endl;

    return 0;
}

同样也是利用编译器在编译的时候进行类型的推导,不同于第一个版本,这次推导在Traits这一层做了特化,针对不同类型的指针类型,做不同的操作,大概就是这样一种思想吧。

相关文章推荐

我对C++ Traits编程技法的一点点理解

第一次听说traits是在一次电话面试中,当时还没有听说过这个词。之后查过资料,但也不是十分明白,直到今天重新看了一下《STL源码剖析》,稍微有一些想法。 1. traits是模板编程里面的一个编程...
  • erorr
  • erorr
  • 2014年04月13日 01:37
  • 1373

《STL源码剖析》学习之traits编程

在设计模式中有一种模式叫迭代器模式,简单来说就是提供一种方法,在不需要暴露某个容器的内部表现形式情况下,使之能依次访问该容器中的各个元素,这种设计思维在STL中得到了广泛的应用,是STL的关键所在,通...
  • shudou
  • shudou
  • 2013年09月15日 20:04
  • 7769

C++traits技术的理解

traits是c++中的自动类型推断,可以用来获得一个类型的相关信息。比如我们有一个泛型的迭代器类,其中T为所指向的类型。 template class myIterator { ... };当我...

三 迭代器(iterator)概念与traits编程技法

第三章 迭代器(iterator)概念与traits编程技法 设计模式中,iterator模式的定义:  提供一种方法,使之能偶依序巡访聚合物(容器)的所含各个元素,而又无需暴露该聚合物的...

STL笔记(7)——Traits编程技法(二)

STL Traits编程技法

Traits编程技法之type_trait

STL对于性能的要求非常的严格,任何一点无意义的操作都会严重影响其中容器或算法的性能,即使只是一条语句。在高频率的使用下,这种浪费将会无限扩大。type_traits的作用之一就是提高性能。 当我们在...

stl源码剖析之traits编程技法

stl中充斥着大量的traits编程技法,要想看stl源码,不了解traits肯定是不行的。 本文主要讲述stl中的taits编程技巧...

STL源码-iterator traits编程技法(续)

// Filename: type_traits.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: ...

STL 迭代器概念及traits编程技法

前言迭代器作为一个抽象概念,在程序设计中并没有直接对应于这个概念的实物。在设计模式中,iterator模式定义为:提供一种方法,能使之依序巡防某个容器所含元素,而无须暴露该容器的内部表达方式。3.1 ...

STL学习笔记(traits编程技法)

为了完成一个迭代器,我们往往会把容器实现的太多细节暴露在w
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:traits编程技法感悟
举报原因:
原因补充:

(最多只允许输入30个字)