【模板进阶】std::true_type和std::false_type

一、 s t d : : t r u e _ t y p e std::true\_type std::true_type s t d : : f a l s e _ t y p e std::false\_type std::false_type的实现

s t d : : t r u e _ t y p e std::true\_type std::true_type s t d : : f a l s e _ t y p e std::false\_type std::false_type实际上是类型别名,经常被使用到。

例如标准库有以下的代码:

在这里插入图片描述
所以,它们实际上是同一个类型的两种特化版本的别名,可以看作是两个类型,也可以看作是一个类型。


下面是 s t d : : t r u e _ t y p e std::true\_type std::true_type s t d : : f a l s e _ t y p e std::false\_type std::false_type的具体实现代码:

//std::true_type和std::false_type的实现代码


template<bool val>
struct BoolConstant {
	using type = BoolConstant;
	
	static constexpr bool value = val;
};

using TrueType = BoolConstant<true>; //相当于std::true_type
using FalseType = BoolConstant<false>;//相当于st::false_type

实际上,这两个类型和 t r u e / f a l s e true/false true/false很类似,实际上就是用一个类来包装它们。
这样的包装有很多好处,比如可以用于作为返回值,也可以作为类被继承等等,下面详细介绍。


二、 s t d : : t r u e _ t y p e std::true\_type std::true_type s t d : : f a l s e _ t y p e std::false\_type std::false_type的用途

2.1 作为返回值使用

考虑以下两个函数:

using TrueType = BoolConstant<true>; //相当于std::true_type
using FalseType = BoolConstant<false>;//相当于st::false_type

//作为返回值来使用
FalseType myfunc1() {

	return FalseType();
}

TrueType myfunc2() {

	return TrueType();
}

void Test1() {
	std::cout << myfunc1().value << "\n";

	std::cout << myfunc2().value << "\n";
	
}

其中一个函数始终返回一个包装 t r u e true true的类,另一个函数返回包装 f a l s e false false的类。


2.2 条件判断,不同类型赋值不同的值

考虑以下的代码:

//条件判断,不同类型赋值不同的值
template<typename T,bool val>
struct AClass {
	AClass() {
		std::cout << "AClass::AClass()执行了!\n";
		//这样编译失败,因为无法确定调用哪一个分支,所以会实例化出所有分支
		if (val) {
			T tmpa = 15;
		}
		else {
			T tmpa = "abc";
		}
};

这样的代码一定会编译失败,因为 i f if if无法在编译期间得到确定,因此全部分支都会被实例化出来。


我们可以考虑使用编译期间的条件分支 i f   c o n s t e x p r if \ constexpr if constexpr来避免这个问题:

//条件判断,不同类型赋值不同的值
template<typename T,bool val>
struct AClass {
	AClass() {
		std::cout << "AClass::AClass()执行了!\n";
		//使用if constexpr在编译期间确定使用的分支
		if constexpr (val) {
			T tmpa = 15;
			std::cout << "tmpa = " << tmpa << "\n";
		}
		else {
			T tmpa = "abc";
			std::cout << "tmpa = " << tmpa << "\n";
		}
	}
};

当然,我们可以使用 s t d : : t r u e _ t y p e std::true\_type std::true_type s t d : : f a l s e _ t y p e std::false\_type std::false_type来达到一样的效果,如下:

template<typename T,bool val>
struct AClass {
	//使用TrueType和FalseType来实现
	AClass() {
		std::cout << "AClass::AClass()执行了!\n";
		AClassEx(BoolConstant<val>()); //临时变量,根据重载的函数来具体实例化
	}

	void AClassEx(TrueType) {
		T tmpa = 15;
		std::cout << "tmpa = " << tmpa << "\n";
	}
	
	void AClassEx(FalseType) {
		T tmpa = "abc";
		std::cout << "tmpa = " << tmpa << "\n";
	}

};

void Test2() {
	AClass<int, true>a1;
	AClass<std::string, false>a2;
	
}

这里同样是在编译期间确定的,因此,如果 v a l val val t r u e true true就调用 T r u e T y p e TrueType TrueType类型的函数,反之调用 F a l s e T y p e FalseType FalseType的函数,这其实利用到了函数重载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值