一、背景
有一个模板函数,函数在处理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
|