| 1 | /*! |
| 2 | @file |
| 3 | Defines function-like equivalents to the standard `<type_traits>`, and also |
| 4 | to some utilities like `std::declval`. |
| 5 | |
| 6 | Copyright Louis Dionne 2013-2022 |
| 7 | Distributed under the Boost Software License, Version 1.0. |
| 8 | (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) |
| 9 | */ |
| 10 | |
| 11 | #ifndef BOOST_HANA_TRAITS_HPP |
| 12 | #define BOOST_HANA_TRAITS_HPP |
| 13 | |
| 14 | #include <boost/hana/config.hpp> |
| 15 | #include <boost/hana/integral_constant.hpp> |
| 16 | #include <boost/hana/type.hpp> |
| 17 | |
| 18 | #include <cstddef> |
| 19 | #include <type_traits> |
| 20 | |
| 21 | |
| 22 | namespace boost { namespace hana { namespace traits { |
| 23 | namespace detail { |
| 24 | // We use this instead of hana::integral because we want to return |
| 25 | // hana::integral_constants instead of std::integral_constants. |
| 26 | template <template <typename ...> class F> |
| 27 | struct hana_trait { |
| 28 | template <typename ...T> |
| 29 | constexpr auto operator()(T const& ...) const { |
| 30 | using Result = typename F<typename T::type...>::type; |
| 31 | return hana::integral_c<typename Result::value_type, Result::value>; |
| 32 | } |
| 33 | }; |
| 34 | } |
| 35 | |
| 36 | /////////////////////// |
| 37 | // Type properties |
| 38 | /////////////////////// |
| 39 | // Primary type categories |
| 40 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_void = detail::hana_trait<std::is_void>{}; |
| 41 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_null_pointer = detail::hana_trait<std::is_null_pointer>{}; |
| 42 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_integral = detail::hana_trait<std::is_integral>{}; |
| 43 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_floating_point = detail::hana_trait<std::is_floating_point>{}; |
| 44 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_array = detail::hana_trait<std::is_array>{}; |
| 45 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_enum = detail::hana_trait<std::is_enum>{}; |
| 46 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_union = detail::hana_trait<std::is_union>{}; |
| 47 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_class = detail::hana_trait<std::is_class>{}; |
| 48 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_function = detail::hana_trait<std::is_function>{}; |
| 49 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_pointer = detail::hana_trait<std::is_pointer>{}; |
| 50 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_lvalue_reference = detail::hana_trait<std::is_lvalue_reference>{}; |
| 51 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_rvalue_reference = detail::hana_trait<std::is_rvalue_reference>{}; |
| 52 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_member_object_pointer = detail::hana_trait<std::is_member_object_pointer>{}; |
| 53 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_member_function_pointer = detail::hana_trait<std::is_member_function_pointer>{}; |
| 54 | |
| 55 | // Composite type categories |
| 56 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_fundamental = detail::hana_trait<std::is_fundamental>{}; |
| 57 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_arithmetic = detail::hana_trait<std::is_arithmetic>{}; |
| 58 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_scalar = detail::hana_trait<std::is_scalar>{}; |
| 59 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_object = detail::hana_trait<std::is_object>{}; |
| 60 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_compound = detail::hana_trait<std::is_compound>{}; |
| 61 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_reference = detail::hana_trait<std::is_reference>{}; |
| 62 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_member_pointer = detail::hana_trait<std::is_member_pointer>{}; |
| 63 | |
| 64 | // Type properties |
| 65 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_const = detail::hana_trait<std::is_const>{}; |
| 66 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_volatile = detail::hana_trait<std::is_volatile>{}; |
| 67 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_trivial = detail::hana_trait<std::is_trivial>{}; |
| 68 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_trivially_copyable = detail::hana_trait<std::is_trivially_copyable>{}; |
| 69 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_standard_layout = detail::hana_trait<std::is_standard_layout>{}; |
| 70 | #if __cplusplus < 202002L |
| 71 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_pod = detail::hana_trait<std::is_pod>{}; |
| 72 | #endif |
| 73 | #if __cplusplus < 201703L |
| 74 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_literal_type = detail::hana_trait<std::is_literal_type>{}; |
| 75 | #endif |
| 76 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_empty = detail::hana_trait<std::is_empty>{}; |
| 77 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_polymorphic = detail::hana_trait<std::is_polymorphic>{}; |
| 78 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_abstract = detail::hana_trait<std::is_abstract>{}; |
| 79 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_signed = detail::hana_trait<std::is_signed>{}; |
| 80 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_unsigned = detail::hana_trait<std::is_unsigned>{}; |
| 81 | |
| 82 | // Supported operations |
| 83 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_constructible = detail::hana_trait<std::is_constructible>{}; |
| 84 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_trivially_constructible = detail::hana_trait<std::is_trivially_constructible>{}; |
| 85 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_nothrow_constructible = detail::hana_trait<std::is_nothrow_constructible>{}; |
| 86 | |
| 87 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_default_constructible = detail::hana_trait<std::is_default_constructible>{}; |
| 88 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_trivially_default_constructible = detail::hana_trait<std::is_trivially_default_constructible>{}; |
| 89 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_nothrow_default_constructible = detail::hana_trait<std::is_nothrow_default_constructible>{}; |
| 90 | |
| 91 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_copy_constructible = detail::hana_trait<std::is_copy_constructible>{}; |
| 92 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_trivially_copy_constructible = detail::hana_trait<std::is_trivially_copy_constructible>{}; |
| 93 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_nothrow_copy_constructible = detail::hana_trait<std::is_nothrow_copy_constructible>{}; |
| 94 | |
| 95 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_move_constructible = detail::hana_trait<std::is_move_constructible>{}; |
| 96 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_trivially_move_constructible = detail::hana_trait<std::is_trivially_move_constructible>{}; |
| 97 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_nothrow_move_constructible = detail::hana_trait<std::is_nothrow_move_constructible>{}; |
| 98 | |
| 99 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_assignable = detail::hana_trait<std::is_assignable>{}; |
| 100 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_trivially_assignable = detail::hana_trait<std::is_trivially_assignable>{}; |
| 101 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_nothrow_assignable = detail::hana_trait<std::is_nothrow_assignable>{}; |
| 102 | |
| 103 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_copy_assignable = detail::hana_trait<std::is_copy_assignable>{}; |
| 104 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_trivially_copy_assignable = detail::hana_trait<std::is_trivially_copy_assignable>{}; |
| 105 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_nothrow_copy_assignable = detail::hana_trait<std::is_nothrow_copy_assignable>{}; |
| 106 | |
| 107 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_move_assignable = detail::hana_trait<std::is_move_assignable>{}; |
| 108 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_trivially_move_assignable = detail::hana_trait<std::is_trivially_move_assignable>{}; |
| 109 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_nothrow_move_assignable = detail::hana_trait<std::is_nothrow_move_assignable>{}; |
| 110 | |
| 111 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_destructible = detail::hana_trait<std::is_destructible>{}; |
| 112 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_trivially_destructible = detail::hana_trait<std::is_trivially_destructible>{}; |
| 113 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_nothrow_destructible = detail::hana_trait<std::is_nothrow_destructible>{}; |
| 114 | |
| 115 | BOOST_HANA_INLINE_VARIABLE constexpr auto has_virtual_destructor = detail::hana_trait<std::has_virtual_destructor>{}; |
| 116 | |
| 117 | // Property queries |
| 118 | BOOST_HANA_INLINE_VARIABLE constexpr auto alignment_of = detail::hana_trait<std::alignment_of>{}; |
| 119 | BOOST_HANA_INLINE_VARIABLE constexpr auto rank = detail::hana_trait<std::rank>{}; |
| 120 | BOOST_HANA_INLINE_VARIABLE constexpr struct extent_t { |
| 121 | template <typename T, typename N> |
| 122 | constexpr auto operator()(T const&, N const&) const { |
| 123 | constexpr unsigned n = N::value; |
| 124 | using Result = typename std::extent<typename T::type, n>::type; |
| 125 | return hana::integral_c<typename Result::value_type, Result::value>; |
| 126 | } |
| 127 | |
| 128 | template <typename T> |
| 129 | constexpr auto operator()(T const& t) const |
| 130 | { return (*this)(t, hana::uint_c<0>); } |
| 131 | } extent{}; |
| 132 | |
| 133 | // Type relationships |
| 134 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_same = detail::hana_trait<std::is_same>{}; |
| 135 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_base_of = detail::hana_trait<std::is_base_of>{}; |
| 136 | BOOST_HANA_INLINE_VARIABLE constexpr auto is_convertible = detail::hana_trait<std::is_convertible>{}; |
| 137 | |
| 138 | /////////////////////// |
| 139 | // Type modifications |
| 140 | /////////////////////// |
| 141 | // Const-volatility specifiers |
| 142 | BOOST_HANA_INLINE_VARIABLE constexpr auto remove_cv = metafunction<std::remove_cv>; |
| 143 | BOOST_HANA_INLINE_VARIABLE constexpr auto remove_const = metafunction<std::remove_const>; |
| 144 | BOOST_HANA_INLINE_VARIABLE constexpr auto remove_volatile = metafunction<std::remove_volatile>; |
| 145 | |
| 146 | BOOST_HANA_INLINE_VARIABLE constexpr auto add_cv = metafunction<std::add_cv>; |
| 147 | BOOST_HANA_INLINE_VARIABLE constexpr auto add_const = metafunction<std::add_const>; |
| 148 | BOOST_HANA_INLINE_VARIABLE constexpr auto add_volatile = metafunction<std::add_volatile>; |
| 149 | |
| 150 | // References |
| 151 | BOOST_HANA_INLINE_VARIABLE constexpr auto remove_reference = metafunction<std::remove_reference>; |
| 152 | BOOST_HANA_INLINE_VARIABLE constexpr auto add_lvalue_reference = metafunction<std::add_lvalue_reference>; |
| 153 | BOOST_HANA_INLINE_VARIABLE constexpr auto add_rvalue_reference = metafunction<std::add_rvalue_reference>; |
| 154 | |
| 155 | // Pointers |
| 156 | BOOST_HANA_INLINE_VARIABLE constexpr auto remove_pointer = metafunction<std::remove_pointer>; |
| 157 | BOOST_HANA_INLINE_VARIABLE constexpr auto add_pointer = metafunction<std::add_pointer>; |
| 158 | |
| 159 | // Sign modifiers |
| 160 | BOOST_HANA_INLINE_VARIABLE constexpr auto make_signed = metafunction<std::make_signed>; |
| 161 | BOOST_HANA_INLINE_VARIABLE constexpr auto make_unsigned = metafunction<std::make_unsigned>; |
| 162 | |
| 163 | // Arrays |
| 164 | BOOST_HANA_INLINE_VARIABLE constexpr auto remove_extent = metafunction<std::remove_extent>; |
| 165 | BOOST_HANA_INLINE_VARIABLE constexpr auto remove_all_extents = metafunction<std::remove_all_extents>; |
| 166 | |
| 167 | // Miscellaneous transformations |
| 168 | BOOST_HANA_INLINE_VARIABLE constexpr struct aligned_storage_t { |
| 169 | template <typename Len, typename Align> |
| 170 | constexpr auto operator()(Len const&, Align const&) const { |
| 171 | constexpr std::size_t len = Len::value; |
| 172 | constexpr std::size_t align = Align::value; |
| 173 | using Result = typename std::aligned_storage<len, align>::type; |
| 174 | return hana::type_c<Result>; |
| 175 | } |
| 176 | |
| 177 | template <typename Len> |
| 178 | constexpr auto operator()(Len const&) const { |
| 179 | constexpr std::size_t len = Len::value; |
| 180 | using Result = typename std::aligned_storage<len>::type; |
| 181 | return hana::type_c<Result>; |
| 182 | } |
| 183 | } aligned_storage{}; |
| 184 | |
| 185 | BOOST_HANA_INLINE_VARIABLE constexpr struct aligned_union_t { |
| 186 | template <typename Len, typename ...T> |
| 187 | constexpr auto operator()(Len const&, T const&...) const { |
| 188 | constexpr std::size_t len = Len::value; |
| 189 | using Result = typename std::aligned_union<len, typename T::type...>::type; |
| 190 | return hana::type_c<Result>; |
| 191 | } |
| 192 | } aligned_union{}; |
| 193 | |
| 194 | BOOST_HANA_INLINE_VARIABLE constexpr auto decay = metafunction<std::decay>; |
| 195 | // enable_if |
| 196 | // disable_if |
| 197 | // conditional |
| 198 | |
| 199 | BOOST_HANA_INLINE_VARIABLE constexpr auto common_type = metafunction<std::common_type>; |
| 200 | BOOST_HANA_INLINE_VARIABLE constexpr auto underlying_type = metafunction<std::underlying_type>; |
| 201 | |
| 202 | |
| 203 | /////////////////////// |
| 204 | // Utilities |
| 205 | /////////////////////// |
| 206 | struct declval_t { |
| 207 | template <typename T> |
| 208 | typename std::add_rvalue_reference< |
| 209 | typename T::type |
| 210 | >::type operator()(T const&) const; |
| 211 | }; |
| 212 | |
| 213 | BOOST_HANA_INLINE_VARIABLE constexpr declval_t declval{}; |
| 214 | } }} // end namespace boost::hana |
| 215 | |
| 216 | #endif // !BOOST_HANA_TRAITS_HPP |
| 217 | |