类型萃取实现vector

本文探讨了C++中如何通过类型萃取技术来识别对象类型,特别提及了在实现过程中遇到的迭代器失效问题及其具体场景,如SeqList、统一内存管理和STL的应用。同时,介绍了POD(Plain Old Data)类型的概念,并给出了一段关于Vector实现的代码示例。

C++中通过类型萃取来实现对象类型的识别。

类型萃取的实际用例:1.SeqList 2.统一内存管理 3.STL

POD:plain old data平凡类型--基本类型,值C++中与C兼容的类型,可以按照C的方式处理


POD类型萃取如下:

#pragma once

struct _TrueType
{};
struct _FlaseType
{};

template <class T>
struct TypeTraits
{
	typedef _FlaseType IsPodType;
};
template <>
struct TypeTraits<int>
{
	typedef _TrueType IsPodType;
};
template <>
struct TypeTraits<char>
{
	typedef _TrueType IsPodType;
};
template <>
struct TypeTraits<double>
{
	typedef _TrueType IsPodType;
};
template<>
struct TypeTraits<float>
{
	typedef _TrueType IsPodType;
};
template <class T>
struct TypeTraits<T*>
{
	typedef _TrueType IsPodType;
};

template <class T>
T* _Copy(T* dst, T* src, size_t n, _FlaseType)
{
	for (size_t i = 0; i < n; i++)
	{
		dst[i] = src[i];
	}
	return dst;
}
template <class T>
T* _Copy(T* dst, T* src, size_t n, _TrueType)
{
	memcpy(dst, src, n*sizeof(T));
	return dst;
}
template <class T>      
T* Copy(T* dst,T* src,size_t n)				//模拟拷贝函数
{
	return _Copy(dst, src, n, TypeTraits<T>::IsPodType());
}

vector顾名思义,是C++中的容器,用以实现对一组数据执行一些操作,如:插入,删除,查找,遍历等,可以用于C++中的任意数据类型,在模拟实现Vector时需要用到上述提到的类型萃取方法,用以识别在使用中对数据类型的识别。

在实现的过程中存在着迭代器失效的问题。迭代器失效是因为在执行删除或插入操作时,在将旧有的数据拷贝到新开辟的空间中,插入或删除数据后,撤销旧的内存空间,造成的指针失效的问题。

具体情况如下:  

 1.当插入(push_back)一个元素后,end操作返回的迭代器肯定失效。

 2.当插入(push_back)一个元素后,capacity返回值与没有插入元素之前相比有改变,则需要重新加载整个容器,此时first和end操作返回的迭代器都会失效。

 3.当进行删除操作(erase,pop_back)后,指向删除点的迭代器全部失效;指向删除点后面的元素的迭代器也将全部失效。

Vector实现代码如下:

#pragma once
#include "TypeTraits.h"

using namespace std;

template <class T>
class Vector
{
public:
	typedef T* Iterator;
	typedef const T* ConstIterator;
	Vector()
		: _start(0)
		, _finsh(0)
		, _endStorage(0)
	{}
	Vector(const Vector<T>& v)
		: _strat(0)
		, _finsh(0)
		, _endStorage(0)
	{
		this->_Expend(v.Size());
		Copy(_start, v._start, v.Size);
		_finsh = _start + v.Size();
		_endStorage = _start + v.Size();
	}
	~Vector()   //注意
	{
		if (_start)
		{
			delete[] _start;
			_start = _finsh = _endStorage = NULL;
		}
	}

	void PushBack(const T& v)
	{
		if (_finsh >= _endStorage)
		{
			size_t capacity = Capacity();
			capacity = capacity + capacity / 2;
			if (capacity < Size() + 1)			//验证是否增容成功
				capacity = Size() + 1;

			_Expend(capacity);
		}

		*_finsh = v;
		++_finsh;
	}

	void Resize(size_t n,const T& val=T())		//重新分配大小,原size和capacity都改变,可预置操作数
	{
		if (n > Capacity())
		{
			_Expend(n);
		}
		if (n > Size())
		{
			Iterator pos = finsh; 
			while (pos != (_start + n))
			{
				*pos = val;
				++pos;
			}
		}
		else if (n < Size())
		{
			Iterator npos = _start + n;
			while (npos != _finsh)
			{
				npos->~T();			//析构由npos之后的空间
			}
			_finsh = _start + n;	//有疑问????
		}
	}

	void Reserve(size_t n)		//预留空间,只改变capacity
	{
		_Expend(n);
	}

	void PopBack()			   //存在迭代器失效的问题
	{
		if (_start == NULL)
			return;

		if (_start == _finsh)
		{
			_finsh->~T();		//如果只有一个元素时
		}
		else
		{
			Iterator del = _finsh;
			
			--_finsh;
			del->~T();
		}

	}
	
	Iterator Find(const T& x)		//查找该值是否存在,存在的位置
	{
		Iterator cur = _start; 
		while (cur < _finsh)
		{
			if (*cur == x)
			{
				return cur;
			}
			++cur;
		}

		return NULL;
	}
	void Erase(Iterator pos)					//删除位置上的数据
	{
		Iterator cur = pos;

		if (cur == _finsh)
		{										//尾删
			PopBack();
		}
		else
		{
			while (cur < _finsh)
			{
				*cur = *(cur + 1);						//有当前位置向后移动覆盖前一个值
				++cur;
			}
			--_finsh;								//尾部前移
		}
		
	}
	void Insert(Iterator &pos,const T& x)		//在具体的位置插入数据
	{
		if (pos == NULL)
			return;

		if (_finsh == _endStorage)			//判断插入后容量是否足够,同时也判断是否是插入第一个数
			_Expend(Capacity() + 1);
		
		Iterator cur = pos;
		T tem = *pos;
		T next = x;
		while (cur <= _finsh)
		{
			*cur = next;
			next = tem;
			++cur;
			tem = *cur;
		}
		*(++_finsh) = next;
	}

	inline size_t Capacity()
	{
		return _endStorage - _start;
	}
	inline size_t Size()
	{
		return _finsh - _start;
	}
	Iterator Bigin()
	{
		return _start;
	}
	ConstIterator Begin() const
	{
		return _start;
	}
	Iterator End()
	{
		return _finsh;
	}
	ConstIterator End() const
	{
		return _finsh;
	}
	void _Expend(size_t n)
	{
		if (n < Capacity())
			return;
		size_t size = Size();
		T* tem = new T[n];
		Copy(tem, _start, size);

		delete[] _start;
		_start = tem;
		_finsh = _start + size;
		_endStorage = _start + n;
	}
	T& operator[](size_t index)
	{
		if (index>=Size())
			throw out_of_range("out of range");

		return _start[index];
	}
	void Print()
	{
		for (size_t i = 0; i < Size(); i++)
		{
		cout << _start[i]<< " ";
		}
		cout << endl;
	}

protected:
	Iterator _start;
	Iterator _finsh;
	Iterator _endStorage;
};


void TestVector()
{
	Vector<int> v;
	v.PushBack(1);
	v.PushBack(2);
	v.PushBack(3);		//尾插测试
	v.PushBack(4);
	v.PushBack(5);
	v.Print();

	v.PopBack();
	v.Print();
	v.PopBack();
	v.Print();
	v.PopBack();		//尾删测试
	v.Print();
	v.PopBack();
	v.Print();
	v.PopBack();
	v.Print();
	v.PopBack();
	v.Print();
}

void TestVector2()
{
	Vector<int> v;
	v.PushBack(1);
	v.PushBack(2);
	v.PushBack(3);							//尾插测试
	v.PushBack(4);
	v.PushBack(5);
	v.Print();

	//Vector<int>::Iterator it=v.Find(3);  //测试查找函数
	//cout << *it << endl;
	//Vector<int>::Iterator it2 = v.Find(6);  //测试查找函数
	//cout << it2 << endl;
	Vector<int>::Iterator pos = v.Find(3);
	v.Insert(pos, 6);			//插入测试
	v.Print();
	//Vector<int>::Iterator pos2 = v.Find(3);	
	//v.Erase(pos2);				//测试任意位置删除
	//v.Print();
	//Vector<int>::Iterator pos2 = v.Find(1);
	//v.Erase(pos2);				//测试任意位置删除,删头部
	//v.Print();
	//Vector<int>::Iterator pos2 = v.Find(5);
	//v.Erase(pos2);				//测试任意位置删除
	//v.Print();
}



### C++ 类型萃取(Type Traits)的实现原理与使用模式 C++类型萃取机制是一种基于模板元编程的技术,用于在编译时获取和操作类型的属性。这种机制广泛应用于泛型编程中,以实现条件判断、优化代码路径以及确保类型安全。 #### 实现原理 类型萃取的核心是模板特化和 SFINAE(Substitution Failure Is Not An Error)。通过定义通用模板并为特定类型提供特化版本,可以提取类型信息。例如 `std::is_integral` 是标准库中用于判断类型是否为整数类型萃取类: ```cpp #include <type_traits> #include <iostream> int main() { std::cout << std::boolalpha; std::cout << std::is_integral<int>::value << "\n"; // true std::cout << std::is_integral<double>::value << "\n"; // false } ``` SFINAE 技术允许在模板参数推导失败时不报错,而是继续尝试其他可能的重载。这种方式常用于检测某个类型是否支持某种操作或具有某种特性。例如,定义一个萃取类来判断某个类型是否具有 `serialize()` 成员函数: ```cpp #include <iostream> #include <type_traits> template<typename T> class has_serialize { private: template<typename U> static auto test(int) -> decltype(std::declval<U>().serialize(), std::true_type()); template<typename U> static std::false_type test(...); public: static constexpr bool value = decltype(test<T>(0))::value; }; struct MyType { void serialize() const { std::cout << "Serialized\n"; } }; int main() { std::cout << std::boolalpha << has_serialize<MyType>::value << "\n"; // true std::cout << std::boolalpha << has_serialize<int>::value << "\n"; // false } ``` 该方法利用了 SFINAE 原理,在 `decltype` 中进行表达式有效性判断,从而决定是否启用特定的模板分支[^1]。 #### 使用模式 类型萃取在泛型编程中主要用于以下几种场景: ##### 条件编译与函数重载选择 结合 `std::enable_if` 可以根据类型特征选择性地启用模板函数或类模板: ```cpp #include <type_traits> #include <iostream> template<typename T> typename std::enable_if<std::is_integral<T>::value, void>::type print_value(T value) { std::cout << "Integral: " << value << "\n"; } template<typename T> typename std::enable_if<!std::is_integral<T>::value, void>::type print_value(T value) { std::cout << "Non-integral: " << value << "\n"; } int main() { print_value(42); // Integral: 42 print_value(3.14); // Non-integral: 3.14 } ``` ##### 类型转换与内存布局控制 通过 `std::remove_cv`, `std::add_pointer`, `std::aligned_storage` 等萃取工具可以动态调整类型属性,以满足特定平台或接口的需求。例如: ```cpp #include <type_traits> #include <iostream> int main() { using RawType = int; using ConstVolatileType = std::add_cv<RawType>::type; // const volatile int std::cout << std::is_same<ConstVolatileType, const volatile int>::value << "\n"; // true } ``` ##### 提升容器与算法的泛型能力 在 STL 容器和算法中,类型萃取被用来获取迭代器的类别、值类型等信息,从而选择最优的执行路径。例如 `std::iterator_traits` 提供了统一接口访问迭代器属性: ```cpp #include <iterator> #include <vector> #include <iostream> template<typename Iterator> void process_iterator(Iterator it) { typename std::iterator_traits<Iterator>::value_type val = *it; std::cout << "Value type: " << val << "\n"; } int main() { std::vector<int> vec = {1, 2, 3}; process_iterator(vec.begin()); // Value type: 1 } ``` #### 总结 C++ 类型萃取机制通过模板特化和 SFINAE 技术实现了对类型信息的静态分析,并在编译期进行决策,从而提升了程序的性能与安全性。其应用涵盖了从泛型算法优化到自定义类型检查等多个方面。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值