类型萃取:类型比较 Type-Traits Library:type comparisons — C++20
不涉及runtime
只在编译期
Comparing types 类型比较
C++11
支持三种类型:
is_base_of<Base, Derived>
is_convertible<From, To>
is_same<T, U>
C++20
新加了几种:
-
is_pointer_interconvertible_with_class<From, To>
检查一个类型的对象是否与该类型的指定对象指针可互转换
-
is_pointer_interconvertible_base_of<Base, Derived>
检查一个类型的对象是否与该类型的指定子对象指针可互转换
#include <iostream>
#include <type_traits>
using namespace std;class BaseClass
{
public:int a;
};class DerivedClass : public BaseClass
{
public:int b;
};int main(int argc, char* argv[])
{cout << boolalpha << endl;cout << is_base_of<BaseClass, DerivedClass>::value << endl;cout << is_convertible<int, double>::value << endl;cout << is_convertible<int, string>::value << endl;cout << is_same<int, int>::value << endl;}
#include <type_traits>
#include <iostream>struct Foo { int x; };
struct Bar { int y; };struct Baz : Foo, Bar {}; // 非标准布局int main()
{std::cout << std::boolalpha<< std::is_same_v<decltype(&Baz::x), int Baz::*><< std::is_pointer_interconvertible_with_class(&Baz::x) << '\n'<< std::is_pointer_interconvertible_with_class<Baz>(&Baz::x) << '\n';
}
std::is_pointer_interconvertible_with_class - cppreference.com
可能的实现方式
std::is_same
#include <iostream>
#include <type_traits>namespace rgr {template<class T, T v>struct integral_constant {static constexpr T value = v;typedef T value_type;typedef integral_constant type;constexpr operator value_type() const noexcept { return value; }constexpr value_type operator()() const noexcept { return value; } //since c++14};typedef integral_constant<bool, true> true_type; // (2) typedef integral_constant<bool, false> false_type;template<class T, class U>struct is_same : false_type {}; // (3)template<class T>struct is_same<T, T> : true_type {};}int main() {std::cout << '\n';std::cout << std::boolalpha;std::cout << "rgr::is_same<int, const int>::value: " << rgr::is_same<int, const int>::value << '\n'; // (1)std::cout << "rgr::is_same<int, volatile int>::value: " << rgr::is_same<int, volatile int>::value << '\n';std::cout << "rgr::is_same<int, int>::value: " << rgr::is_same<int, int>::value << '\n';std::cout << '\n';std::cout << "std::is_same<int, const int>::value: " << std::is_same<int, const int>::value << '\n';std::cout << "std::is_same<int, volatile int>::value: " << std::is_same<int, volatile int>::value << '\n';std::cout << "std::is_same<int, int>::value: " << std::is_same<int, int>::value << '\n';std::cout << '\n';}
调用函数模板rgr::is_same<int, const int>
就是调用模板函数false_type::value
,因为is_same : false_type {};
忽略const
和volatile
版本
#include <iostream>
#include <type_traits>namespace rgr {template<class T, T v>struct integral_constant {static constexpr T value = v;typedef T value_type;typedef integral_constant type;constexpr operator value_type() const noexcept { return value; }constexpr value_type operator()() const noexcept { return value; } //since c++14};typedef integral_constant<bool, true> true_type; typedef integral_constant<bool, false> false_type;template<class T, class U>struct is_same : false_type {};template<class T>struct is_same<T, T> : true_type {};template<typename T, typename U> // (1)struct isSameIgnoringConstVolatile: rgr::integral_constant<bool,rgr::is_same<typename std::remove_cv<T>::type, typename std::remove_cv<U>::type>::value > {};}int main() {std::cout << '\n';std::cout << std::boolalpha;std::cout << "rgr::isSameIgnoringConstVolatile<int, const int>::value: " << rgr::isSameIgnoringConstVolatile<int, const int>::value << '\n';std::cout << "rgr::is_same<int, volatile int>::value: " << rgr::isSameIgnoringConstVolatile<int, volatile int>::value << '\n';std::cout << "rgr::isSameIgnoringConstVolatile<int, int>::value: " << rgr::isSameIgnoringConstVolatile<int, int>::value << '\n';std::cout << '\n';}
使用std::remove_cv
移除const
和volatile
std::is_base_of
namespace details {template <typename B>std::true_type test_pre_ptr_convertible(const volatile B*);template <typename>std::false_type test_pre_ptr_convertible(const volatile void*);template <typename, typename>auto test_pre_is_base_of(...) -> std::true_type;template <typename B, typename D>auto test_pre_is_base_of(int) ->decltype(test_pre_ptr_convertible<B>(static_cast<D*>(nullptr)));
}template <typename Base, typename Derived>
struct is_base_of :std::integral_constant<bool,std::is_class<Base>::value && std::is_class<Derived>::value &&decltype(details::test_pre_is_base_of<Base, Derived>(0))::value> { };
std::is_convertible
namespace detail {template<class T>
auto test_returnable(int) -> decltype(void(static_cast<T(*)()>(nullptr)), std::true_type{}
);
template<class>
auto test_returnable(...) -> std::false_type;template<class From, class To>
auto test_implicitly_convertible(int) -> decltype(void(std::declval<void(&)(To)>()(std::declval<From>())), std::true_type{}
);
template<class, class>
auto test_implicitly_convertible(...) -> std::false_type;} // namespace detailtemplate<class From, class To>
struct is_convertible : std::integral_constant<bool,(decltype(detail::test_returnable<To>(0))::value &&decltype(detail::test_implicitly_convertible<From, To>(0))::value) ||(std::is_void<From>::value && std::is_void<To>::value)
> {};
这东西好难,智商太低…
最全C++11/14/17/20/23 的新特性代码案例 - 知乎 (zhihu.com)
The Type-Traits Library: Type Comparisons - ModernesCpp.com