一、 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的函数,这其实利用到了函数重载。