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::enable_if
模板类型
template<bool B, class T = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };
用法一:类型偏特化
在使用模板编程时,经常会用到根据模板参数的某些特性进行不同类型的选择,或者在编译时校验模板参数的某些特性。
template <typename T, typename Enable=void>
struct check;
template <typename T>
struct check<T, typename std::enable_if<T::value, T>::type> {
static constexpr bool value = T::value;
};
上述的 check 只希望选择 value==true 的 T,否则就报编译时错误。如果想给用户更友好的提示,可以提供结构体的原型定义,并在其中进行 static_assert 的静态检查,给出更明确的字符串说明。
用法二:控制函数返回类型
对于模板函数,有时希望根据不同的模板参数返回不同类型的值,进而给函数模板也赋予类型模板特化的性质。典型的例子可以参看 tuple
的获取第 k 个元素的 get
函数:
template <std::size_t k, class T, class... Ts>
typename std::enable_if<k==0, typename element_type_holder<0, T, Ts...>::type&>::type
get(tuple<T, Ts...> &t) {
return t.tail;
}
template <std::size_t k, class T, class... Ts>
typename std::enable_if<k!=0, typename element_type_holder<k, T, Ts...>::type&>::type
get(tuple<T, Ts...> &t) {
tuple<Ts...> &base = t;
return get<k-1>(base);
}
由于函数模板不能偏特化,通过 enable_if
便可以根据 k
值的不同情况选择调用哪个 get
,进而实现函数模板的多态。
用法三:校验函数模板参数类型
有时定义的模板函数,只希望特定的类型可以调用,参考 cppreference 官网示例,很好的说明了如何限制只有整型可以调用的函数定义:
template <typename T>
typename std::enable_if<std::is_integral<T>::value, bool>::type
is_odd(T t) {
return bool(t%2);
}
template <typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
bool is_even(T t) {
return !is_odd(t);
}
一个通过返回值,一个通过默认模板参数,都可以实现校验模板参数是整型的功能。
std::enable_if_t
模板类型
template <bool _Test, class _Ty = void>
using enable_if_t = typename enable_if<_Test, _Ty>::type;
和std::enable_if的功能类似。
用法
class B {};
class C {};
template <typename T, typename std::enable_if<std::is_same<T, B>::value, T>::type* = nullptr>
void HandleType(T type);
template <typename T, typename std::enable_if_t<std::is_same<T, B>::value>* = nullptr>
void HandleType(T type);