您好,欢迎访问代理记账网站
移动应用 微信公众号 联系我们

咨询热线 -

电话 15988168888

联系客服
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

C++的std::is_same与std::decay

一、背景

有一个模板函数,函数在处理int型和double型时需要进行特殊的处理,那么怎么在编译期知道传入的参数的数据类型是int型还是double型呢?

#include <iostream>
template<typename T>

void typeCheck(T data)
{
    // check data type
    //std::cout<< out put the type
}

二、std::is_same

<type_traits>头文件中提供了C++ STL的std::is_same模板。 C++ STL的std::is_same模板用于检查类型A是否与类型B相同。如果两者相同,则返回布尔值true,否则返回false。

模板类型

template <class A, class B>
struct is_same

template <class A, class B>
inline constexpr 
       bool is_same_v
         = is_same<A, B>::value

用法

std::is_same<A, B>::value

实例

#include <iostream>
#include <type_traits>
#include <cstdint>

int main()
{
    //使bool型变量按照false、true的格式输出。
    //如不使用该标识符,那么结果会按照1、0的格式输出。
    std::cout << std::boolalpha;

    // usually true if 'int' is 32 bit
    std::cout << std::is_same<int, std::int32_t>::value << ' '; // ~ true
    std::cout << std::is_same<int, std::int64_t>::value << ' '; // ~ false

    // same tests as above, except using C++17's `std::is_same_v<T, U>` format
    std::cout << std::is_same_v<int, std::int32_t> << ' ';  // ~ true
    std::cout << std::is_same_v<int, std::int64_t> << '\n'; // ~ false

    // compare the types of a couple variables
    long double num1 = 1.0;
    long double num2 = 2.0;
    std::cout << std::is_same_v<decltype(num1), decltype(num2)> << '\n'; // true

    // 'float' is never an integral type
    std::cout << std::is_same<float, std::int32_t>::value << '\n'; // false

    // 'int' is implicitly 'signed'
    std::cout << std::is_same<int, int>::value << ' ';          // true
    std::cout << std::is_same<int, unsigned int>::value << ' '; // false
    std::cout << std::is_same<int, signed int>::value << '\n';  // true

    system("pause");
    return 0;

}

打印

 

四、新的问题

std::is_same可以判断两种类似是否一样,那么用在模板里就是利器了,比如直接在编译的时候判断类型

#include <iostream>
template<typename TYPE>
typeCheck(TYPE data)
{
    if(std::is_same<TYPE,int>::value)
    {
        std::cout<<"int type";
        //do something int 
    }
    else
    {
        //.........
    }
}

让我们试一试

// is_same example
#include <iostream>
#include <type_traits>
#include <cstdint>

typedef int integer_type;

struct A { 
    int x;
    int y;
};

struct B { 
int x;
int y; 
};

typedef A C;

int main() {
      std::cout << std::boolalpha;
      std::cout << "is_same:" << std::endl;
      std::cout << "int, const int: " << std::is_same<int, const int>::value << std::endl;//false
      std::cout << "int, int&: " << std::is_same<int, int&>::value << std::endl;//false
      std::cout << "int, const int&: " << std::is_same<int, const int&>::value << std::endl;//false
      std::cout << "int, integer_type: " << std::is_same<int, integer_type>::value << std::endl;//true
      std::cout << "A, B: " << std::is_same<A,B>::value << std::endl;//false
      std::cout << "A, C: " << std::is_same<A,C>::value << std::endl;//true
      std::cout << "signed char, std::int8_t: " << std::is_same<signed char,std::int8_t>::value << std::endl;//true
      return 0;
}

打印

发现std::is_same的判断是很严格的.std::is_same对int和const int\int &\const int&等都是区别对待的,但在写模板函数时,经常会强制指定常引用进行传参,以免进行数据拷贝,这时候is_same就做出了不相等的判断,但是有时候其实我们还是希望TYPE和const TYPE& 是能认为是一样的,这时就需要std::decay进行退化处理。
 

四、std::decay

C++11提供了一个模板类,来为我们移除类型中的一些特性,比如引用、常量、volatile,但是注意不包括指针特性。std::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;
};

 实例

#include <iostream>
#include <type_traits>

template <typename T, typename U>
struct decay_equiv : 
    std::is_same<typename std::decay<T>::type, U>::type 
{};

int main()
{
    std::cout << std::boolalpha
              << decay_equiv<int, int>::value << '\n'
              << decay_equiv<int&, int>::value << '\n'
              << decay_equiv<int&&, int>::value << '\n'
              << decay_equiv<const int&, int>::value << '\n'
              << decay_equiv<int[2], int*>::value << '\n'
              << decay_equiv<int(int), int(*)(int)>::value << '\n';
    return 0;
}

打印

 

参考:

C++11的模板类型判断——std::is_same和std::decay_尘中远的博客-CSDN博客_std::decay

std::is_same - cppreference.com

std::decay - cppreference.com

【C++11】C++类型完全退化(拓展std::decay的功能)_几罗星人的博客-CSDN博客_std::decay


分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进