C++ Type Trait

本文介绍了C++中的Type Trait,它是一种处理类型属性的模板,可以在编译时根据模板参数产生类型或值。文章讨论了如何使用Type Trait进行整数类型的弹性重载,处理共通类型,以及深入探讨了Type Trait的相关工具和类型关系检验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

所谓Type trait提供一种用来处理type属性的办法。它是一个模板,可在编译器根据一或多个模板实参产出一个type或value

示例如下:
在这里插入图片描述

针对整数类型的弹性重载

假设有一个函数foo(),对于整数类型和浮点数类型的实参,它该有不同的实现。通常的做法是将它重载,使它拥有针对整数类型和针对浮点数类型两个版本:

void foo(short);
void foo(int);
void foo(float);
void foo(double);
void foo(long double);
...

这样的重复工作不仅令人厌烦,还带来一个问题:只要面对新类型或用户自定义的类型,它就束手无策了
有了type trait,你可以这样写:

template<typename T>
void foo_impl(T val, true_type);
template<typename T>
void foo_impl(T val, false_type);
template<typename T>
void foo(T val)
{
	foo_impl(val, std::is_integral<T>());
}

处理共通类型

不同类型的两个值的总和或最小值就该使用所谓的共通类型。否则,如果我想实现一个函数,判断不同类型的两值中的最小值,其返回类型该是什么呢?

template<typename T1, typename T2>
???min(const T1 & x, const T2 & x);

如果使用type trait,可以像这样解决问题:

template<typename T1, typename T2>
typename std::common_type<T1,T2>::type min(const T1 & x, const T2 & y);

如果两个实参是int 或都是long,或一个是int一个是long,会产出int,如果一个是string另一个是const char*,返回string

这么办到的?

template<typename T1, typename T2>
struct common_type<T1,T2>
{
	typedef decltype(true? declval<T1>() : declval<T2>())type;
}

declval<>是个辅助性trait,依据传入的类型,提供一个rvalue reference
如果?:能够找到一个共通类型,common_type<>就会产出它

细究Type Trait

Type Trait通常被定义于<type_traits>

下面是一些类型判断工具:

is_void<T> //类型void
is_integral<T>//整数类型 bool、char、等
is_floating_point<T>//浮点数类型
is_arithmetic<T>//整数或浮点数类型
is_signed<T>//带正负号的算术类型
is_unsigned<T>//不带正负号的算术类型
is_const<T>//带有const限定符
is_volatile<T>//带有volatile限定符
is_array<T>//寻常的array类型 不是std::array
is_enum<T>//枚举类型
is_union<T>//联合类型
is_class<T>//class/struct类型,但不是union类型
is_function<T>//函数类型
is_reference<T>//左值引用或右值引用
is_lvalue_reference<T>//左值引用
is_rvalue_reference<T>//右值引用
is_pointer<T>//指针类型包括函数指针,不包括指向非静态成员的指针
is_member_pointer<T>//指向非静态成员指针
is_member_object_pointer<T>//指针,指向一个非静态数据成员
is_member_function_pointer<T>//指针,指向一个非静态成员函数
is_fundamental<T>//void,整数型,浮点数或者nullptr_t
is_scalar<T>//整数型、浮点数、枚举、nullptr_t
is_object<T>//任何类型,除了void、function、reference
is_compound<T>//array、enum、union、class、reference、pointer
is_trivial<T>//scalar、trival class或那些
...

针对类类型设计的工具如下:

is_empty<T> //class不带任何成员、virtual成员函数或virtual base class
is_polymorphic<T>//class带有一个virtual成员函数 
is_abstract<T>//抽象类即至少有一个纯虚函数
has_virtual_destructor<T>//类带有一个虚析构函数
is_default_constructible<T>//class能够完成默认构造
is_copy_constructible<T>//class能够完成复制构造
is_move_constructible<T>//class能够完成移动构造
is_copy_assignable<T>//class能够完成复制赋值
is_move_assignable<T>//class能够完成移动赋值
is_destructible<T>//class带有可被调用的析构函数(不可以是deleted、Protected、private)
...

用来检验类型关系的Trait

is_same<T1,T2>//检验T1和T2是否是相同类型
is_base_of<T,D>//T是类型D的基类
is_convertible<T,T2>//类型T可转换至类型T2
is_constructible<T,Args...>//可运用类型Args初始化T
....

类型修饰符

下面的trait允许你改动类型

remove_const<T>//对应不带const的类型
remove_volatile<T>//对应不带volatile的类型
remove_cv<T>//对应不带const volatile
add_const<T>//对应之const类型
add_volatile<T>//对应之volatile的类型
add_cv<T>//对应之const volatile类型
make_signed<T>//对应之带正负号的非引用类型
make_unsigned<T>//对应之不带正负号的非引用类型
remove_reference<T>//对应之非引用类型
add_lvalue_reference<T>//对应之左值引用类型
add_rvalue_reference<T>//对应之右值引用类型
remove_pointer<T>//指针所指针的类型
add_pointer<T>//指针类型,指向对应的非引用类类型
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值