#pragma once namespace util { template <typename T, T V> struct integral_constant {static constexpr T value = V;}; struct true_type : integral_constant<bool, true> {}; struct false_type : integral_constant<bool, false> {}; inline constexpr bool true_type_v = true_type::value; inline constexpr bool false_type_v = false_type::value; namespace detail { template <class T> struct type_identity { using type = T; }; // or use std::type_identity (since C++20) template <class T> // Note that `cv void&` is a substitution failure auto try_add_lvalue_reference(int) -> type_identity<T &>; template <class T> // Handle T = cv void case auto try_add_lvalue_reference(...) -> type_identity<T>; template <class T> auto try_add_rvalue_reference(int) -> type_identity<T &&>; template <class T> auto try_add_rvalue_reference(...) -> type_identity<T>; } // namespace detail template <class T> struct add_lvalue_reference : decltype(detail::try_add_lvalue_reference<T>(0)) { }; template <class T> struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference<T>(0)) { }; template <class T> using add_rvalue_reference_t = typename add_rvalue_reference<T>::type; template <class T> add_rvalue_reference_t<T> declval() noexcept { #pragma clang diagnostic push static_assert(false, "Calling declval is ill-formed, see N4892 [declval]/2."); #pragma clang diagnostic pop } namespace detail { template <class T> auto test_returnable(int) -> decltype(void(static_cast<T (*)()>(nullptr)), true_type{}); template <class> auto test_returnable(...) -> false_type; template <class From, class To> auto test_implicitly_convertible(int) -> decltype(void(declval<void (&)(To)>()(declval<From>())), true_type{}); template <class, class> auto test_implicitly_convertible(...) -> false_type; } // namespace detail template <typename T> struct is_void : false_type{}; template<> struct is_void<void> : true_type {}; template <typename T> inline constexpr bool is_void_v = is_void<T>::value; template< class T > struct remove_reference { typedef T type; }; template< class T > struct remove_reference<T&> { typedef T type; }; template< class T > struct remove_reference<T&&> { typedef T type; }; template< class T > using remove_reference_t = typename remove_reference<T>::type; }