C++类模板特化应用之类型萃取

1.使用memcpy拷贝

template<class T>
void Copy(T* dst, const T* src, size_t size)
{
	memcpy(dst, src, sizeof(T)*size);
}
int main()
{
	// 试试下面的代码
	std::string strarr1[3] = { "11", "22", "33" };
	std::string strarr2[3];
	Copy(strarr2, strarr1, 3);
	return 0;
}

上述代码虽然对于任意类型的空间都可以进行拷贝,但是如果拷贝自定义类型对象就可能会出错,因为自定义类型对象有可能会涉及到深拷贝(比如string),而memcpy属于浅拷贝(若拷贝的资源内有指针,则拷贝的是地址而不是指针所指向的资源)。如果对象中涉及到资源管理,就只能用赋值。

2 使用赋值方式拷贝
缺点:循环赋值的方式虽然可以,但是代码的效率比较低

template<class T>
void Copy(T* dst, const T* src, size_t size)
{
    for(size_t i = 0; i < size; ++i)
    {
        dst[i] = src[i];
    }
}

3. 增加bool类型区分自定义与内置类型

template<class T>
void Copy(T* dst, const T* src, size_t size, bool IsPODType)
{
    if(IsPODType)
    memcpy(dst, src, sizeof(T)*size);
    else
    {
        for(size_t i = 0; i < size; ++i)
        dst[i] = src[i];
    }
}

缺点:用户需要根据所拷贝元素的类型去传递第三个参数,那出错的可能性就增加。

4.类型萃取

//为了将内置类型与自定义类型区分开,给出以下两个类分别代表内置类型与自定义类型。
// 代表内置类型
struct TrueType
{
	static bool Get()
	{
		return true;
	}
};
// 代表自定义类型
struct FalseType
{
	static bool Get()
	{
		return false;
	}
};

//给出以下类模板,将来用户可以按照任意类型实例化该类模板。
template<class T>
struct TypeTraits
{
	typedef FalseType IsPODType;
};

//对上述的类模板进行以下方式的实例化
template<>
struct TypeTraits<char>
{
	typedef TrueType IsPODType;
};
template<>
struct TypeTraits<short>
{
	typedef TrueType IsPODType;
};
template<>
struct TypeTraits<int>
{
	typedef TrueType IsPODType;
};
template<>
struct TypeTraits<long>
{
	typedef TrueType IsPODType;
};
template<>
struct TypeTraits<long long>
{
	typedef TrueType IsPODType;
};
template<>
struct TypeTraits<long double>
{
	typedef TrueType IsPODType;
};
template<>
struct TypeTraits<float>
{
	typedef TrueType IsPODType;
};
template<>
struct TypeTraits<double>
{
	typedef TrueType IsPODType;
};

template<class T>
void Copy(T* dst, const T* src, size_t size)
{
	if (TypeTraits<T>::IsPODType::Get())
		memcpy(dst, src, sizeof(T)*size);
	else
	{
		for (size_t i = 0; i < size; ++i)
			dst[i] = src[i];
	}
}
int main()
{
	int a1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	int a2[10];
	Copy(a2, a1, 10);  //调用memcpy
	string s1[] = { "1111", "2222", "3333", "4444" };
	string s2[4];
	Copy(s2, s1, 4); //执行for循环
	return 0;
}

拓展:STL中类型萃取的例子
①注意:在重载内置类型时,所有的内置类型都必须重载出来,包括有符号和无符号,比如:对于int类型,必须特化三个,int – signed int – unsigned int
②在需要区分内置类型与自定义类型的位置,标准库通常都是通过__true_type与__false_type给出一对重载的函数,然后用一个通用函数对其进行封装
③注意:第四个参数可以不提供名字,该参数最主要的作用就是让两个_copy函数形成重载

// 代表内置类型
struct __true_type {};
// 代表自定义类型
struct __false_type {};

template <class type>
struct __type_traits
{
    typedef __false_type is_POD_type;
};

// 对所有内置类型进行特化
template<>
struct __type_traits<char>
{
typedef __true_type is_POD_type;
};
...........这里就只举一个char的例子

template<class T>
void _copy(T* dst, T* src, size_t n, __true_type)
{
    memcpy(dst, src, n*sizeof(T));
}

template<class T>
void _copy(T* dst, T* src, size_t n, __false_type)
{
    for (size_t i = 0; i < n; ++i)
    dst[i] = src[i];
}

template<class T>
void Copy(T* dst, T* src, size_t n)
{
     _copy(dst, src, n, __type_traits<T>::is_POD_type());
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值