C/C++编程:Type Trait

本文介绍了TypeTrait的概念及其在C++中的应用。TypeTrait是一种用于处理类型属性的模板,它能够在编译时期根据类型参数生成特定的类型或值。文章通过实例展示了如何使用TypeTrait来简化类型检查和处理共通类型的问题。

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

什么是Type Trait

 

所谓type trait,提供一种用来处理type属性的办法

 

它是个template,可以在编译器根据一个或者多个template实参(通常也是type)产生一个type或者value

 

请看下面例子:

template <typename T>
void foo(const T& val) {
    if (std::is_pointer<T>::value) {
        cout << "foo called for a pointer " << endl;
    }
    else
        cout << "foo() called for a value" << endl;
    //...
}

trait std::is_pointer定义于<type_traits>,用来检查T是否pointer type。若是,就是 type true_type,否则type false_type。而::value若非产生true就是false。

但是,不能如下这么做:

template <typename T>
void foo(const T& val) {
    std::cout << (std::is_pointer<T>::value ? *val : val) << endl;
}

原因是,代码扩展后会同时产生*val和val,如果你传递一个int使编译器表达式is_point<T>::value产生false,代码会被扩展为:

std::is_pointer<T>::value ? *val : val

这是不能通过变异的,因为当“val是个整数”时,*val是一个无效表达式。

但是你可以这样做:

template <typename T>
void fool_impl(const T& val,std::true_type){
    cout << "foo() called for pointer to " << *val << endl;
}

template<typename T>
void fool_impl(const T7 val, std::false_type){
    cout << "foo() called value to  "<< val << endl;
}

template<typename T>
void foo(const T& val){
    fool_impl(val,std::is_pointer<T>());
}

这比重载版本要好。是因为,有时候太多重载版本并无必要。

 

一般而言,type trait 的威力来自于一个事实:它们是泛型代码的基石。下面两个例子可以说明这个观点

  •  针对整数的弹性重载

假设一个函数foo(),对于整数类型和浮点类型的实参有不同的实现。通常做法是重载:

void foo(short);
void foo(unsigned 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(const T& val){
    fool_impl(val,std::is_integral<T>());
}

只需提供两份实现,整数和浮点,完事儿。

  • 处理共通类型

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

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

这时如果运用type trait,就可以解决问题:

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

如果两个实参都是int 或者都是long,或者一个是int一个是long,std::common_type<T1,T2>::type 会产生int。如果实参之一是string而另一个是字符串字面常量,就产生std::string.  

怎么办到的?实际上,它只是使用了操作符?:的规则而已:

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

其中 decltype是c++11提供的关键字,用以到处表达式类型,declval()是辅助性trait,依据传入的类型提供一个值 ,但是不去核算它

 

 Type Trait探讨

 

头文件

#include <type_traits>

成员函数变量等具体是怎么用的

 

 

 

 

 

 

 

 

 


 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值