【C++】type_trait的conditional、conjunction、enable_if、is_iterable、is_lvalue_reference实现分析

conditional
template<bool B, class T, class F>
struct conditional { typedef T type; };
 
template<class T, class F>
struct conditional<false, T, F> { typedef F type; };

template< bool B, class T, class F >
using conditional_t = typename conditional<B,T,F>::type;
conjunction
template<class...> struct conjunction : std::true_type { };
template<class B1> struct conjunction<B1> : B1 { };
template<class B1, class... Bn>
struct conjunction<B1, Bn...> 
    : std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};

template<class... B>
inline constexpr bool conjunction_v = conjunction<B...>::value;
enable_if
template<bool B, class T = void>
struct enable_if {};
 
template<class T>
struct enable_if<true, T> { typedef T type; };

template< bool B, class T = void >
using enable_if_t = typename enable_if<B,T>::type;
is_iterable
template <typename T, typename = void>
struct is_iterable : std::false_type {};
template <typename T>
struct is_iterable<T, std::void_t<decltype(std::declval<T>().begin()),
                                  decltype(std::declval<T>().end())>>
    : std::true_type {};
is_lvalue_reference

template<class T> struct is_lvalue_reference     : std::false_type {};
template<class T> struct is_lvalue_reference<T&> : std::true_type {};

template< class T >
inline constexpr bool is_lvalue_reference_v = is_lvalue_reference<T>::value;
integral_constant

template<class T, T v>
struct integral_constant {
    static constexpr T value = v;
    using value_type = T;
    using type = integral_constant; // 使用注入类名
    constexpr operator value_type() const noexcept { return value; }
    constexpr value_type operator()() const noexcept { return value; } // C++14 起
};
is_convertible
namespace detail {
 
template<class>
using true_type_for = std::true_type;
 
template<class T>
auto test_returnable(int) -> true_type_for<T()>;
template<class>
auto test_returnable(...) -> std::false_type;
 
template<class From, class To>
auto test_nonvoid_convertible(int) -> true_type_for<
    decltype(std::declval<void(&)(To)>()(std::declval<From>()))
>;
template<class, class>
auto test_nonvoid_convertible(...) -> std::false_type;
 
} // namespace detail
 
template<class From, class To>
struct is_convertible : std::integral_constant<bool,
    (decltype(detail::test_returnable<To>(0))::value &&
     decltype(detail::test_nonvoid_convertible<From, To>(0))::value) ||
    (std::is_void<From>::value && std::is_void<To>::value)
> {};
Published 431 original articles · Liked 14 · Visitors 100,000+

Guess you like

Origin blog.csdn.net/LU_ZHAO/article/details/105503022