请支持原创~~
0. 前言
在 《c++11 std::is_same》https://justinwei.blog.csdn.net/article/details/120268292https://justinwei.blog.csdn.net/article/details/120268292中提到is_same 是严格的类型比对,包含了CV 属性的对比,例如 int 和const int 在is_same 中不是一个类型,返回值也是为false。但是有些时候我们想要排除CV属性进行浅层次比对,怎么办?本文的decay 可以做到!
1. 头文件
#include <type_traits>
2. 声明
template <class T> struct decay; //c++11
template <class T>using decay_t = typename decay<T>::type; // C++14
decay 是在c++11 发布的,在c++14中发布了decay_t 用以标记decay 的type。
3. 实现
实现大致如下,下面是代码整合后的结果,实际在type_traits 中,成员变量type 是在 struct __decay 中定义的。
template< class T >
struct decay {
private:
typedef typename std::remove_reference<T>::type U;
public:
typedef typename std::conditional<
std::is_array<U>::value,
typename std::remove_extent<U>::type*,
typename std::conditional<
std::is_function<U>::value,
typename std::add_pointer<U>::type,
typename std::remove_cv<U>::type
>::type
>::type type;
};
为类型T应用从左值到右值(lvalue-to-rvalue)、数组到指针(array-to-pointer)和函数到指针(function-to-pointer)的隐式转换。转换将移除类型T的cv限定符(const和volatile限定符),并定义结果类型为成员decay<T>::type的类型。这种转换很类似于当函数的所有参数按值传递时发生转换。
- 如果类型T是一个函数类型,那么从函数到指针的类型转换将被应用,并且T的衰变类型等同于:add_pointer<T>::type
- 如果类型T是一个数组类型,那么从数组到指针的类型转换将被应用,并且T的衰变类型等同于:add_pointer<remove_extent<remove_reference<T>::type>::type>::type
- 当左值到右值转换被应用时,T的衰变类型等同于:remove_cv<remove_reference<T>::type>::type
这里涉及到remove_reference,这也是type_traits 中的类型,通过名称就可以看出来,主要根据T 取出& 或 && 得到最后的type,去除引用的属性:
template <class _Tp> struct remove_reference {typedef _Tp type;};
template <class _Tp> struct remove_reference<_Tp&> {typedef _Tp type;};
template <class _Tp> struct remove_reference<_Tp&&> {typedef _Tp type;};
同理,remove_cv 也是将const 和volatile 的属性用typedef 的方式去掉:
template <class _Tp> struct remove_volatile {typedef _Tp type;};
template <class _Tp> struct remove_volatile<volatile _Tp> {typedef _Tp type;};
当然,详细的还有下面的这些,从名称就可以知道具体使用:
template <class T> struct remove_const;
template <class T> struct remove_volatile;
template <class T> struct remove_pointer;
template <class T> struct remove_extent;
...
这里就不做过多的介绍
4. 实例
#include <iostream>
#include <type_traits>
typedef std::decay<int>::type A; // int
typedef std::decay<int&>::type B; // int
typedef std::decay<int&&>::type C; // int
typedef std::decay<const int&>::type D; // int
typedef std::decay<int[2]>::type E; // int*
typedef std::decay<int(int)>::type F; // int(*)(int)
typedef int X[3];
int main() {
std::cout << std::boolalpha;
std::cout << "typedefs of int:" << std::endl;
std::cout << "A: " << std::is_same<int,A>::value << std::endl;
std::cout << "B: " << std::is_same<int,B>::value << std::endl;
std::cout << "C: " << std::is_same<int,C>::value << std::endl;
std::cout << "D: " << std::is_same<int,D>::value << std::endl;
std::cout << "E: " << std::is_same<int,E>::value << std::endl;
std::cout << "F: " << std::is_same<int,F>::value << std::endl;
return 0;
}
运行结果:
typedefs of int:
A: true
B: true
C: true
D: true
E: false
F: false
5. 总结
std::decay 主要是弱化一些类型,说白了就是通过typedef 的方式去除掉引用、cv等属性。一般std::decay 与std::is_same 配合使用,确认基础类型。