stl中的conditional_t是干嘛的?

stl源码中,有个很基础的类型conditional_t,conditional_t有什么用?在回答这个问题之前,先看几个简单的例子。

现在有如下需求,有两个类A、B,如下:

struct A
{
	int a= 10;
};
struct B
{
	float b = 200.0f;
};

问题1:现在新加一个类O,我希望它有时候继承A,有时候继承B,该怎么办?

我们知道,一般继承情况下,O要么继承A,要么继承B,要么多继承A、B,怎么会既可能继承A,又可能继承B呢?从描述中,我们得出一个信息:O继承的类型是不固定的。而C++中,应付可变类型的技巧是什么?模板!Good,解决方法诞生了!

template<typename T>
struct O:public T
{};

//使用代码如下
O<A> o1; //O继承A
O<B> o2; //O继承B

接下来,继续看一个稍微变化的例子,以上代码中,O继承谁,完全是O自己说了算。

问题2:如果由外部给定一个参数,然后O根据这个参数来决定继承A还是B,该怎么办?


template<typename T>
void function(T t)
{
    O ? //不同的T如何生成不同的O?
}

O继承的类型依然不固定,所以还是从模板编程下手,本情况下,外部还要传入参数,可见O的模板中必须接受一个外部参数。我们可以利用模板特化,写出如下代码:

template<typename T>
struct O: public A
{};

template<>
struct O<int>: public B
{};


template<typename T>
void function(T t)
{
    O<T> o;
}

//使用代码如下
function<int>();  //其中O<int> o; O继承B
function<char>(); //其中O<char> o; O继承A

这里的O有瑕疵,什么瑕疵?这种代码写完后,O只能继承A或者B了,解决方法也很简单,把A、B也抽到模板参数里面,于是有如下代码

template<typename T, typename A, typename B>
struct O: public A
{};

template<typename A, typename B>
struct O<int, A, B>: public B
{};


template<typename T>
void function(T t)
{
    O<T,A,B> o;
}

//使用代码如下
function<int>();  //其中O<int> o; O继承B
function<char>(); //其中O<char> o; O继承A

这样function里面,O可以通过修改模板的实际参数,来选择继承别的类。

问题3:O解决了选择继承的问题,我现在又写了一个新的类C,我希望C也能像O那样,怎么办?难道要像捣鼓O那样再捣鼓C一次?

再捣鼓C一次,明显是一种糟糕的做法,我们很希望有如下这种代码:

template<typename T, typename A, typename B>
class O:public <..把选择AB的过程放到这里解决..>
{};

这样,假如C也需要这个功能,只要把public后面的东西摘过去就行了,和O的本体代码不发生任何纠纷。<....>最好返回一个type,这个type由T A B三个模板参数决定,吸取之前两个方案的经验和技巧,我们可以写出如下代码:

template<typename T, typename A, typename B>
struct select_type
{
	using Type = A;
};
template<typename A, typename B>
struct select_type <int,A,B>
{
	using Type = B;
};

//这个select_t起到一个转接的作用
template<typename T, typename A, typename B>
using select_t = typename select_type<T, A, B>::Type;

template<typename T,typename A,typename B>
struct O :public select_t<T, A, B>
{

};

//使用代码
O<char, A, B > o1; //O继承A
O<int , A, B > o1; //O继承B

Good!我们成功把选择A、B的过程从O中剥离出来了,如果C也要这样,直接把public select<T,A,B>摘到C后面去就行了!方便!

好了,例子看完了,说回conditional_t,让我们看看conditional_t的源码:

	// STRUCT TEMPLATE conditional
template<bool _Test,
	class _Ty1,
	class _Ty2>
	struct conditional
	{	// type is _Ty2 for assumed !_Test
	using type = _Ty2;
	};

template<class _Ty1,
	class _Ty2>
	struct conditional<true, _Ty1, _Ty2>
	{	// type is _Ty1 for _Test
	using type = _Ty1;
	};

template<bool _Test,
	class _Ty1,
	class _Ty2>
	using conditional_t = typename conditional<_Test, _Ty1, _Ty2>::type;

仔细一看,这和我们写的select_t几乎一模一样!所以conditional_t的设计目标就很明显了:在编译期,给定不同的参数,返回不同的类型!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值