类型萃取

类型萃取是实现不同类型数据面对同一函数实现不同的操作,它与类封装的区别是:并不用知道所调用的对象是什么类型,类型萃取是编译后知道类型,先实现;而类的封装则是先定义类型,后实现方法。

类型分为基本类型(POD),和自定义类型。

在这里用模板的特化实现其编程思想:

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

程序:

#include<iostream>

using namespace std;

#include<string>

struct __TrueType

{

static bool Get()

{

return true;

}

};

struct __FalseType

{

static bool Get()

{

return false;

}

};

template <class T>

struct TypeTraits//traits为特性

{

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();

//    s1.PrintSeqList();

//}

//string的测试函数

void Test()

{

SeqList<string> s2;

s2.PushBack("Hello");

s2.PushBack("yaoyao! ");

s2.PrintSeqList();

s2.PrintSeqList();

}

int main()

{

Test();

system("pause");

return 0;

}

运行结果:

Hello  yaoyao!

Hello  yaoyao!

请按任意键继续. . .

时间: 2024-12-09 15:28:06

类型萃取的相关文章

c++ 类型萃取(模板类型 运用)

//类型萃取 #pragma once #include<iostream> using namespace std; struct __TrueType//定义类 普通类型(基本类型的) { bool Get() { return true; } }; struct __FalseType//定义类 非基本类型 { bool Get() { return false; } }; template <class _Tp>//模板类 (类型萃取) struct TypeTraits 

头一回发博客,来分享个有关C++类型萃取的编写技巧

废话不多说,上来贴代码最实在,哈哈! 以下代码量有点多,不过这都是在下一手一手敲出来的,小巧好用,把以下代码复制出来,放到相应的hpp文件即可,VS,GCC下均能编译通过 1 #include<iostream> 2 #include "../../traits/traits.hpp" 3 4 5 using namespace std; 6 7 8 int show(char i, int j) 9 { 10 return 1; 11 } 12 13 struct Stu

C++_模板类与类型萃取技术

在声明变量,函数,和大多数其他类型实体的时候,C++要求我们使用指定的类型.然而,有许多代码,除了类型不同之外,其余部分看起来都是相同的,比如,下面这个例子: bool IsEqual (int left, int right) {     return left == right; } bool IsEqual (const string& left , const string& right) {     return left == right; } void test() {   

通过模板的特化实现 简单的类型萃取 实现memcppy时候对于特殊类型如string类的拷贝。

C++怎样识别一个对象的类型? typeid可以获取到一个类型的名称,但是不能拿来做变量的声明. [POD类型萃取] // // POD: plain old data 平凡类型(无关痛痒的类型)--基本类型 // 指在C++ 中与 C兼容的类型,可以按照 C 的方式处理. //#include<iostream> #include<string> using namespace std; struct __TrueType {  bool Get()  {   return tr

【干货】C++通过模板特化实现类型萃取实例--实现区分基本类型与自定义类型的memcpy

类型萃取是一种常用的编程技巧,其目的是实现不同类型数据面对同一函数实现不同的操作,如STL中cout的实现,它与类封装的区别是,我们并不用知道我们所调用的对象是什么类型,类型萃取是编译器后知道类型,先实现,而类的封装则是先定义类型,后实现方法.在这里我们可以用模板的特化实现其编程思想. 我们以memcpy为例,当我们拷贝的是基本类型时,只用拷贝所传递指针上的数据,如果是string类型呢,我们则需要在堆上开辟空间,所传递的指针如果被直接复制,则有可能(vs下的string类型的实现原理是若字符串

C++ 模板 之 类型萃取 与 容器适配器

类型萃取 在模板这里主要就是对于模板的不同类型的实例化 有不同的方案 这样可以提高效率等 比如 下面的 顺序表 在扩容时的拷贝 对于没有含有指向空间的指针的类 如int 自动使用memcpy() 对于含有指向空间的指针的类 如string 就自动一个一个的赋值 防止浅拷贝导致两个指针指向同一空间 析构两次时出错 类型萃取实现 主要用到了 模板  模板特化 内嵌型别  也可用函数重载 详见Copy() //(1)-------类型萃取 实现顺序表 //----------------------C

STL的迭代器和类型萃取

今天就可以把STL库中迭代器的实现,和类型萃取好好整理一下了 迭代器的设计思维是STL的关键所在,在STL的实际运用和泛型思维,迭代器都扮演着十分重要的角色,STL力求把数据容器和算法的概念分开来,于是就有了STL的两大部分,容器(container)和泛型算法(algorithms),泛型算法有很多参数都是迭代器. 举一个栗子!泛型算法find()的实现! 1 template<class InputIterator, class T> 2 InputIterator find(InputI

第17课 类型萃取(1)_基本的type_traits

1. type_traits类型萃取 (1)type_traits通过定义一些结构体或类,并利用模板类特化和偏特化的能力,给类型赋予一些特性,这些特性根据类型的不同而异.在程序设计中可以使用这些traits来判断一个类型的一些特性,引发C++的函数重载机制,实现同一种操作因类型不同而异的效果. (2)type_traits提供了丰富的编译期计算.查询.判断.转换和选择的帮助类. (3)type_traits的类型选择功能,在一定程序上可以消除冗长的switch-cast或if-else的语句.提

SGI-STL简记(三)-构造、类型萃取特性、未初始化解析

stl_construct.h : 提供多种构造器.销毁器模板函数: 构造器construct提供了给定值构造和默认构造方式,通过调用重载函数_Construct实现: 销毁器destroy提供了销毁指针和迭代器的方式,通过调用重载函数_Destroy实现: _Construct:通过“放置”new,构造实现: _Destroy:通过调用模板类型对象析构函数实现,对于迭代器器方式,则通过__destroy(内部通过__destroy_aux)遍历销毁,因内置数据类型不需要销毁, 故内部需要判断是