78 lines
2.3 KiB
C++
78 lines
2.3 KiB
C++
#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;
|
|
} |