【C++】类型萃取技术实现静态顺序表

原创 2016年05月30日 17:18:15

类型萃取是一种常用的编程技巧,其目的是实现不同类型数据面对同一函数实现不同的操作,它与类封装的区别是,我们并不用知道我 们所调用的对象是什么类型,类型萃取是编译后知道类型,先实现,而类的封装则是先定义类型,后实现方法。在这里我们可以用模板的特化实现其编程思想。


我们以memcpy为例,当我们拷贝的是基本类型时,只用拷贝所传递指针上的数据,如果是string类型呢,我们则需要在堆上开辟空间,所传递的指针如 果被直接复制,则有可能(vs下的string类型的实现原理是若字符串不长则以数组保存,若字符串过长,则通过指针在堆上开辟空间进行保存)出现同一地 址,析构两次这样的常见错误。


我们知道,类型分为基本类型(POD),和自定义类型。基本类型指C++ 中与C兼容的类型,可以按照 C 的方式处理。而自定义类型如我们今天实现的静态顺序表。

代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include<string>

struct __TrueType
{
    bool Get()
    {
        return true;
    }
};

struct __FalseType
{
    bool Get()
    {
        return false;
    }
};

template <class T>
struct TypeTraits
{
    typedef __FalseType   __IsPODType;
};

template <>
struct TypeTraits< bool>
{
    typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< char>
{
    typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< unsigned char >
{
    typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< short>
{
    typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits< unsigned short >
{
    typedef __TrueType     __IsPODType;
};

template <>
struct TypeTraits<int>
{
    typedef __TrueType __IsPODType;
};

template<class T>
void _Memcpy(T& dest, const T& src, size_t size, __TrueType)    //基本类型
{
    cout << "IsPOD::" << typeid(T).name() << endl;
    memcpy(dest, src, sizeof(T)*size);
}

template<class T>
void _Memcpy(T& dest, const T& src, size_t size, __FalseType)
{
    cout << "IsNotPOD::"<<typeid(T).name() << endl;
    for (int i = 0; i < size; i++)
    {
        dest[i] = src[i];
    }
}

template<class T>
class SeqList
{
public:
    SeqList()
        :_size(0)
        , _capacity(0)
        , _array(NULL)
    {}

    SeqList<T>(const SeqList<T>& s)
    {
        _array = new T[s._size];
        if (TypeTraits <T>::__IsPODType().Get())
        {
            _Memcpy(_array, s._array, s._size, TypeTraits<T>::__IsPODType());
        }
        else
        {
            _Memcpy(_array, s._array, s._size, TypeTraits<T>::__IsPODType());
        }
        swap(_size, s._size);
        swap(_capacity, s._capacity);
    }

    SeqList<T>& operator= (SeqList<T> s)
    {
        swap(_array, s._array);
        swap(_size, s._size);
        swap(_capacity, s._capacity);
    }

    ~SeqList()
    {
        if (_array)
        {
            delete[] _array;
            _array = NULL;
        }
    }

    void _CheckCapacity(size_t n)
    {
        if (n > _capacity)
        {
            _capacity = 2 * _capacity + 3;
            T* tmp = new T[_capacity];
            if (_array != NULL)
            {
                if (TypeTraits <T>::__IsPODType().Get())
                {
                    _Memcpy(tmp, _array, _size, TypeTraits <T>::__IsPODType());
                }
                else
                {
                    _Memcpy(tmp, _array, _size, TypeTraits <T>::__IsPODType());
                }
            }            
            delete[] _array;
            _array = NULL;
            _array = tmp;
        }
    }

    void PushBack(const T& x);
    void PopBack();
    void PrintSeqList();

private:
    size_t _size;
    size_t _capacity;
    T* _array;
};


template<class T>
void SeqList<T>:: PushBack(const T& x)
{
    _CheckCapacity(_size + 1);
    _array[_size++] = x;    
}

template<class T>
void SeqList<T>:: PopBack()
{
    if (_size == 0)
    {
        return;
    }
    else
    {
        --_size;
    }
}

template<class T>
void SeqList<T>:: PrintSeqList()
{
    for (int i = 0; i < _size; i++)
    {
        cout << _array[i] << "  ";
    }
    cout << endl;
}


//int的测试函数
//void Test()
//{
//    SeqList<int> s1;
//    s1.PushBack(1);
//    s1.PushBack(2);
//    s1.PushBack(3);
//    s1.PushBack(4);
//    s1.PushBack(5);
//    s1.PrintSeqList();

//  s2.PopBack();
//  s2.PrintSeqList();
//}

//string的测试函数
void Test()
{
    SeqList<string> s2;
    s2.PushBack("hello ");
    s2.PushBack("world ");
    s2.PushBack("I ");
    s2.PushBack("love ");
    s2.PushBack("IT");
    s2.PrintSeqList();

    s2.PopBack();
    s2.PrintSeqList();
}


int main()
{
    Test();
    system("pause");
    return 0;
}

本文出自 “Han Jing's Blog” 博客,请务必保留此出处http://10740184.blog.51cto.com/10730184/1752747

C++ 模板类型萃取技术 traits

自从C++中引入了template后,以泛型技术为中心的设计得到了长足的进步。STL就是这个阶段杰出的产物。STL的目标就是要把数据和算法分开,分别对其进行设计,之后通过一种名为iterator的东西...
  • net_assassin
  • net_assassin
  • 2013年08月09日 16:20
  • 2333

C++的类型萃取技术

C++的类型萃取技术 自从C++中引入了template后,以泛型技术为中心的设计得到了长足的进步。STL就是这个阶段杰出的产物。STL的目标就是要把数据和算法分开,分别对其进行设计,之后通过一...
  • natsu1211
  • natsu1211
  • 2014年05月06日 02:05
  • 872

数据结构之“查找”-1:静态查找表

静态查找表,一般情况下,数据是比较稳定的,很少变动的。所以,可以不考虑构造成本(即一次构造,会使用很多很多次)。     首先,当然是我们常用的:顺序查找。即,一个一个往后找,找到就找到。常用数据结构...
  • cainiaohhf
  • cainiaohhf
  • 2014年01月05日 17:10
  • 1376

C++的类型萃取技术

http://www.cppblog.com/nacci/archive/2005/11/03/911.aspx?spm=0.0.0.0.iyJqvt&file=911.aspx
  • sunmenggmail
  • sunmenggmail
  • 2014年05月11日 17:10
  • 449

c++顺序表基本算法代码

#include #include using namespace std; #define MAXLEN 100//定义顺序表的最大长度 /*************顺序表的定义部分*******...
  • cherishwangq
  • cherishwangq
  • 2016年11月02日 09:50
  • 728

C++的类型萃取技术

从C++中引入了template后,以泛型技术为中心的设计得到了长足的进步。STL就是这个阶段杰出的产物。STL的目标就是要把数据和算法分开,分别对其进行设计,之后通过一种名为iterator的东西,...
  • zdy0_2004
  • zdy0_2004
  • 2014年09月30日 00:17
  • 299

算法学习之查找算法:静态查找表(1)顺序表查找

引言:         查找表一般
  • To_Be_IT_1
  • To_Be_IT_1
  • 2014年09月22日 06:44
  • 1830

用c++实现 c++顺序表的实现(采用模板)

函数实现数据的插入(头插&&尾插)、删除(头删&&尾删)、查找、按位置插入、按位置删除、顺序表求长、顺序表清除、顺序表摧毁、数据的逆置以及数据排序   main函数 #include"SeqList....
  • S0Soul
  • S0Soul
  • 2015年05月25日 11:26
  • 1992

c++::关于类型萃取

听到类型萃取这个名字,很多人肯定都感觉好高大上啊,会不会很难,是个什么东西呢?别着急,听我娓娓道来。 【类型萃取】说白了就是对模板特化的一种应用。 1、类型萃取的作用:类型萃取使用模板技术来萃取类...
  • lalu58
  • lalu58
  • 2016年11月13日 17:36
  • 4336

【STL】类型萃取(TypeTraits)

为什么需要类型萃取前面我们提到了迭代器,它是一个行为类似于smart pointer之类的东西,主要用于对STL容器中的对象进行访问,而且不暴露容器中的内部结构,而迭代器所指对象的型别称为该迭代器的v...
  • bit_clearoff
  • bit_clearoff
  • 2016年12月18日 17:06
  • 840
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【C++】类型萃取技术实现静态顺序表
举报原因:
原因补充:

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