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-2017
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 BOOST_HANA_NAMESPACE_BEGIN 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>
operator ()traits::detail::hana_trait29             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     constexpr auto is_void = detail::hana_trait<std::is_void>{};
41     constexpr auto is_null_pointer = detail::hana_trait<std::is_null_pointer>{};
42     constexpr auto is_integral = detail::hana_trait<std::is_integral>{};
43     constexpr auto is_floating_point = detail::hana_trait<std::is_floating_point>{};
44     constexpr auto is_array = detail::hana_trait<std::is_array>{};
45     constexpr auto is_enum = detail::hana_trait<std::is_enum>{};
46     constexpr auto is_union = detail::hana_trait<std::is_union>{};
47     constexpr auto is_class = detail::hana_trait<std::is_class>{};
48     constexpr auto is_function = detail::hana_trait<std::is_function>{};
49     constexpr auto is_pointer = detail::hana_trait<std::is_pointer>{};
50     constexpr auto is_lvalue_reference = detail::hana_trait<std::is_lvalue_reference>{};
51     constexpr auto is_rvalue_reference = detail::hana_trait<std::is_rvalue_reference>{};
52     constexpr auto is_member_object_pointer = detail::hana_trait<std::is_member_object_pointer>{};
53     constexpr auto is_member_function_pointer = detail::hana_trait<std::is_member_function_pointer>{};
54 
55     // Composite type categories
56     constexpr auto is_fundamental = detail::hana_trait<std::is_fundamental>{};
57     constexpr auto is_arithmetic = detail::hana_trait<std::is_arithmetic>{};
58     constexpr auto is_scalar = detail::hana_trait<std::is_scalar>{};
59     constexpr auto is_object = detail::hana_trait<std::is_object>{};
60     constexpr auto is_compound = detail::hana_trait<std::is_compound>{};
61     constexpr auto is_reference = detail::hana_trait<std::is_reference>{};
62     constexpr auto is_member_pointer = detail::hana_trait<std::is_member_pointer>{};
63 
64     // Type properties
65     constexpr auto is_const = detail::hana_trait<std::is_const>{};
66     constexpr auto is_volatile = detail::hana_trait<std::is_volatile>{};
67     constexpr auto is_trivial = detail::hana_trait<std::is_trivial>{};
68     constexpr auto is_trivially_copyable = detail::hana_trait<std::is_trivially_copyable>{};
69     constexpr auto is_standard_layout = detail::hana_trait<std::is_standard_layout>{};
70 #if __cplusplus < 202002L
71     constexpr auto is_pod = detail::hana_trait<std::is_pod>{};
72 #endif
73     constexpr auto is_literal_type = detail::hana_trait<std::is_literal_type>{};
74     constexpr auto is_empty = detail::hana_trait<std::is_empty>{};
75     constexpr auto is_polymorphic = detail::hana_trait<std::is_polymorphic>{};
76     constexpr auto is_abstract = detail::hana_trait<std::is_abstract>{};
77     constexpr auto is_signed = detail::hana_trait<std::is_signed>{};
78     constexpr auto is_unsigned = detail::hana_trait<std::is_unsigned>{};
79 
80     // Supported operations
81     constexpr auto is_constructible = detail::hana_trait<std::is_constructible>{};
82     constexpr auto is_trivially_constructible = detail::hana_trait<std::is_trivially_constructible>{};
83     constexpr auto is_nothrow_constructible = detail::hana_trait<std::is_nothrow_constructible>{};
84 
85     constexpr auto is_default_constructible = detail::hana_trait<std::is_default_constructible>{};
86     constexpr auto is_trivially_default_constructible = detail::hana_trait<std::is_trivially_default_constructible>{};
87     constexpr auto is_nothrow_default_constructible = detail::hana_trait<std::is_nothrow_default_constructible>{};
88 
89     constexpr auto is_copy_constructible = detail::hana_trait<std::is_copy_constructible>{};
90     constexpr auto is_trivially_copy_constructible = detail::hana_trait<std::is_trivially_copy_constructible>{};
91     constexpr auto is_nothrow_copy_constructible = detail::hana_trait<std::is_nothrow_copy_constructible>{};
92 
93     constexpr auto is_move_constructible = detail::hana_trait<std::is_move_constructible>{};
94     constexpr auto is_trivially_move_constructible = detail::hana_trait<std::is_trivially_move_constructible>{};
95     constexpr auto is_nothrow_move_constructible = detail::hana_trait<std::is_nothrow_move_constructible>{};
96 
97     constexpr auto is_assignable = detail::hana_trait<std::is_assignable>{};
98     constexpr auto is_trivially_assignable = detail::hana_trait<std::is_trivially_assignable>{};
99     constexpr auto is_nothrow_assignable = detail::hana_trait<std::is_nothrow_assignable>{};
100 
101     constexpr auto is_copy_assignable = detail::hana_trait<std::is_copy_assignable>{};
102     constexpr auto is_trivially_copy_assignable = detail::hana_trait<std::is_trivially_copy_assignable>{};
103     constexpr auto is_nothrow_copy_assignable = detail::hana_trait<std::is_nothrow_copy_assignable>{};
104 
105     constexpr auto is_move_assignable = detail::hana_trait<std::is_move_assignable>{};
106     constexpr auto is_trivially_move_assignable = detail::hana_trait<std::is_trivially_move_assignable>{};
107     constexpr auto is_nothrow_move_assignable = detail::hana_trait<std::is_nothrow_move_assignable>{};
108 
109     constexpr auto is_destructible = detail::hana_trait<std::is_destructible>{};
110     constexpr auto is_trivially_destructible = detail::hana_trait<std::is_trivially_destructible>{};
111     constexpr auto is_nothrow_destructible = detail::hana_trait<std::is_nothrow_destructible>{};
112 
113     constexpr auto has_virtual_destructor = detail::hana_trait<std::has_virtual_destructor>{};
114 
115     // Property queries
116     constexpr auto alignment_of = detail::hana_trait<std::alignment_of>{};
117     constexpr auto rank = detail::hana_trait<std::rank>{};
118     constexpr struct extent_t {
119         template <typename T, typename N>
operator ()traits::extent_t120         constexpr auto operator()(T const&, N const&) const {
121             constexpr unsigned n = N::value;
122             using Result = typename std::extent<typename T::type, n>::type;
123             return hana::integral_c<typename Result::value_type, Result::value>;
124         }
125 
126         template <typename T>
operator ()traits::extent_t127         constexpr auto operator()(T const& t) const
128         { return (*this)(t, hana::uint_c<0>); }
129     } extent{};
130 
131     // Type relationships
132     constexpr auto is_same = detail::hana_trait<std::is_same>{};
133     constexpr auto is_base_of = detail::hana_trait<std::is_base_of>{};
134     constexpr auto is_convertible = detail::hana_trait<std::is_convertible>{};
135 
136     ///////////////////////
137     // Type modifications
138     ///////////////////////
139     // Const-volatility specifiers
140     constexpr auto remove_cv = metafunction<std::remove_cv>;
141     constexpr auto remove_const = metafunction<std::remove_const>;
142     constexpr auto remove_volatile = metafunction<std::remove_volatile>;
143 
144     constexpr auto add_cv = metafunction<std::add_cv>;
145     constexpr auto add_const = metafunction<std::add_const>;
146     constexpr auto add_volatile = metafunction<std::add_volatile>;
147 
148     // References
149     constexpr auto remove_reference = metafunction<std::remove_reference>;
150     constexpr auto add_lvalue_reference = metafunction<std::add_lvalue_reference>;
151     constexpr auto add_rvalue_reference = metafunction<std::add_rvalue_reference>;
152 
153     // Pointers
154     constexpr auto remove_pointer = metafunction<std::remove_pointer>;
155     constexpr auto add_pointer = metafunction<std::add_pointer>;
156 
157     // Sign modifiers
158     constexpr auto make_signed = metafunction<std::make_signed>;
159     constexpr auto make_unsigned = metafunction<std::make_unsigned>;
160 
161     // Arrays
162     constexpr auto remove_extent = metafunction<std::remove_extent>;
163     constexpr auto remove_all_extents = metafunction<std::remove_all_extents>;
164 
165     // Miscellaneous transformations
166     constexpr struct aligned_storage_t {
167         template <typename Len, typename Align>
operator ()traits::aligned_storage_t168         constexpr auto operator()(Len const&, Align const&) const {
169             constexpr std::size_t len = Len::value;
170             constexpr std::size_t align = Align::value;
171             using Result = typename std::aligned_storage<len, align>::type;
172             return hana::type_c<Result>;
173         }
174 
175         template <typename Len>
operator ()traits::aligned_storage_t176         constexpr auto operator()(Len const&) const {
177             constexpr std::size_t len = Len::value;
178             using Result = typename std::aligned_storage<len>::type;
179             return hana::type_c<Result>;
180         }
181     } aligned_storage{};
182 
183     constexpr struct aligned_union_t {
184         template <typename Len, typename ...T>
operator ()traits::aligned_union_t185         constexpr auto operator()(Len const&, T const&...) const {
186             constexpr std::size_t len = Len::value;
187             using Result = typename std::aligned_union<len, typename T::type...>::type;
188             return hana::type_c<Result>;
189         }
190     } aligned_union{};
191 
192     constexpr auto decay = metafunction<std::decay>;
193     // enable_if
194     // disable_if
195     // conditional
196 
197     constexpr auto common_type = metafunction<std::common_type>;
198     constexpr auto underlying_type = metafunction<std::underlying_type>;
199 
200 
201     ///////////////////////
202     // Utilities
203     ///////////////////////
204     struct declval_t {
205         template <typename T>
206         typename std::add_rvalue_reference<
207             typename T::type
208         >::type operator()(T const&) const;
209     };
210 
211     constexpr declval_t declval{};
212 } BOOST_HANA_NAMESPACE_END
213 
214 #endif // !BOOST_HANA_TRAITS_HPP
215