]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/hana/type.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / hana / type.hpp
1 /*!
2 @file
3 Defines `boost::hana::type` and related utilities.
4
5 @copyright Louis Dionne 2013-2017
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8 */
9
10 #ifndef BOOST_HANA_TYPE_HPP
11 #define BOOST_HANA_TYPE_HPP
12
13 #include <boost/hana/fwd/type.hpp>
14
15 #include <boost/hana/bool.hpp>
16 #include <boost/hana/config.hpp>
17 #include <boost/hana/core/when.hpp>
18 #include <boost/hana/detail/operators/adl.hpp>
19 #include <boost/hana/detail/operators/comparable.hpp>
20 #include <boost/hana/fwd/concept/metafunction.hpp>
21 #include <boost/hana/fwd/core/make.hpp>
22 #include <boost/hana/fwd/equal.hpp>
23 #include <boost/hana/fwd/hash.hpp>
24 #include <boost/hana/integral_constant.hpp>
25
26 #include <type_traits>
27 #include <utility>
28
29
30 namespace boost { namespace hana {
31 //////////////////////////////////////////////////////////////////////////
32 // basic_type
33 //////////////////////////////////////////////////////////////////////////
34 //! @cond
35 template <typename T>
36 struct basic_type : detail::operators::adl<basic_type<T>> {
37 using hana_tag = type_tag;
38
39 using type = T;
40 constexpr auto operator+() const { return *this; }
41 };
42 //! @endcond
43
44 //////////////////////////////////////////////////////////////////////////
45 // type
46 //////////////////////////////////////////////////////////////////////////
47 template <typename T>
48 struct type_impl {
49 struct _ : basic_type<T> { };
50 };
51
52 //////////////////////////////////////////////////////////////////////////
53 // decltype_
54 //////////////////////////////////////////////////////////////////////////
55 namespace detail {
56 template <typename T, typename = type_tag>
57 struct decltype_t {
58 using type = typename std::remove_reference<T>::type;
59 };
60
61 template <typename T>
62 struct decltype_t<T, typename hana::tag_of<T>::type> {
63 using type = typename std::remove_reference<T>::type::type;
64 };
65 }
66
67 //! @cond
68 template <typename T>
69 constexpr auto decltype_t::operator()(T&&) const
70 { return hana::type_c<typename detail::decltype_t<T>::type>; }
71 //! @endcond
72
73 //////////////////////////////////////////////////////////////////////////
74 // typeid_
75 //////////////////////////////////////////////////////////////////////////
76 namespace detail {
77 template <typename T, typename = type_tag>
78 struct typeid_t {
79 using type = typename std::remove_cv<
80 typename std::remove_reference<T>::type
81 >::type;
82 };
83
84 template <typename T>
85 struct typeid_t<T, typename hana::tag_of<T>::type> {
86 using type = typename std::remove_reference<T>::type::type;
87 };
88 }
89 //! @cond
90 template <typename T>
91 constexpr auto typeid_t::operator()(T&&) const
92 { return hana::type_c<typename detail::typeid_t<T>::type>; }
93 //! @endcond
94
95 //////////////////////////////////////////////////////////////////////////
96 // make<type_tag>
97 //////////////////////////////////////////////////////////////////////////
98 template <>
99 struct make_impl<type_tag> {
100 template <typename T>
101 static constexpr auto apply(T&& t)
102 { return hana::typeid_(static_cast<T&&>(t)); }
103 };
104
105 //////////////////////////////////////////////////////////////////////////
106 // sizeof_
107 //////////////////////////////////////////////////////////////////////////
108 //! @cond
109 template <typename T>
110 constexpr auto sizeof_t::operator()(T&&) const
111 { return hana::size_c<sizeof(typename detail::decltype_t<T>::type)>; }
112 //! @endcond
113
114 //////////////////////////////////////////////////////////////////////////
115 // alignof_
116 //////////////////////////////////////////////////////////////////////////
117 //! @cond
118 template <typename T>
119 constexpr auto alignof_t::operator()(T&&) const
120 { return hana::size_c<alignof(typename detail::decltype_t<T>::type)>; }
121 //! @endcond
122
123 //////////////////////////////////////////////////////////////////////////
124 // is_valid
125 //////////////////////////////////////////////////////////////////////////
126 namespace type_detail {
127 template <typename F, typename ...Args, typename = decltype(
128 std::declval<F&&>()(std::declval<Args&&>()...)
129 )>
130 constexpr auto is_valid_impl(int) { return hana::true_c; }
131
132 template <typename F, typename ...Args>
133 constexpr auto is_valid_impl(...) { return hana::false_c; }
134
135 template <typename F>
136 struct is_valid_fun {
137 template <typename ...Args>
138 constexpr auto operator()(Args&& ...) const
139 { return is_valid_impl<F, Args&&...>(int{}); }
140 };
141 }
142
143 //! @cond
144 template <typename F>
145 constexpr auto is_valid_t::operator()(F&&) const
146 { return type_detail::is_valid_fun<F&&>{}; }
147
148 template <typename F, typename ...Args>
149 constexpr auto is_valid_t::operator()(F&&, Args&& ...) const
150 { return type_detail::is_valid_impl<F&&, Args&&...>(int{}); }
151 //! @endcond
152
153 //////////////////////////////////////////////////////////////////////////
154 // template_
155 //////////////////////////////////////////////////////////////////////////
156 // Note: We have to use the very complicated trick below instead of just
157 // mentionning `F<T...>` in a SFINAE-able context because of CWG 1430
158 // (http://www.open-std.org/Jtc1/sc22/wg21/docs/cwg_active.html#1430).
159 namespace template_detail {
160 template <typename ...T> struct args;
161 template <typename ...> using always_void = void;
162
163 template <template <typename ...> class F, typename Args, typename = void>
164 struct specialization_is_valid
165 : std::false_type
166 { };
167
168 template <template <typename ...> class F, typename ...T>
169 struct specialization_is_valid<F, args<T...>, always_void<F<T...>>>
170 : std::true_type
171 { };
172 } // end namespace detail
173
174 template <template <typename ...> class F>
175 struct template_t {
176 template <typename ...T>
177 struct apply {
178 using type = F<T...>;
179 };
180
181 template <typename ...T, typename = std::enable_if_t<
182 template_detail::specialization_is_valid<F, template_detail::args<typename T::type...>>::value
183 >>
184 constexpr auto operator()(T const& ...) const
185 { return hana::type<F<typename T::type...>>{}; }
186 };
187
188 //////////////////////////////////////////////////////////////////////////
189 // metafunction
190 //////////////////////////////////////////////////////////////////////////
191 template <template <typename ...> class F>
192 struct metafunction_t {
193 template <typename ...T>
194 using apply = F<T...>;
195
196 template <typename ...T>
197 constexpr hana::type<typename F<typename T::type...>::type>
198 operator()(T const& ...) const { return {}; }
199 };
200
201 //////////////////////////////////////////////////////////////////////////
202 // metafunction_class
203 //////////////////////////////////////////////////////////////////////////
204 namespace detail {
205 template <typename F, typename ...T>
206 struct always_first { using type = F; };
207 }
208 template <typename F>
209 struct metafunction_class_t {
210 template <typename ...T>
211 using apply = typename detail::always_first<F, T...>::type::template apply<T...>;
212
213 template <typename ...T>
214 constexpr hana::type<typename detail::always_first<F, T...>::type::template apply<typename T::type...>::type>
215 operator()(T const& ...) const { return {}; }
216 };
217
218 //////////////////////////////////////////////////////////////////////////
219 // Metafunction
220 //////////////////////////////////////////////////////////////////////////
221 template <template <typename ...> class F>
222 struct Metafunction<template_t<F>> {
223 static constexpr bool value = true;
224 };
225
226 template <template <typename ...> class F>
227 struct Metafunction<metafunction_t<F>> {
228 static constexpr bool value = true;
229 };
230
231 template <typename F>
232 struct Metafunction<metafunction_class_t<F>> {
233 static constexpr bool value = true;
234 };
235
236 //////////////////////////////////////////////////////////////////////////
237 // integral
238 //////////////////////////////////////////////////////////////////////////
239 template <typename F>
240 struct integral_t {
241 template <typename ...T, typename Result =
242 typename detail::always_first<F, T...>::type::template apply<typename T::type...>::type
243 >
244 constexpr Result operator()(T const& ...) const {
245 return Result{};
246 }
247 };
248
249 //////////////////////////////////////////////////////////////////////////
250 // Operators
251 //////////////////////////////////////////////////////////////////////////
252 namespace detail {
253 template <>
254 struct comparable_operators<type_tag> {
255 static constexpr bool value = true;
256 };
257 }
258
259 //////////////////////////////////////////////////////////////////////////
260 // Comparable
261 //////////////////////////////////////////////////////////////////////////
262 template <>
263 struct equal_impl<type_tag, type_tag> {
264 template <typename T, typename U>
265 static constexpr auto apply(basic_type<T> const&, basic_type<U> const&)
266 { return hana::false_c; }
267
268 template <typename T>
269 static constexpr auto apply(basic_type<T> const&, basic_type<T> const&)
270 { return hana::true_c; }
271 };
272
273 //////////////////////////////////////////////////////////////////////////
274 // Hashable
275 //////////////////////////////////////////////////////////////////////////
276 template <>
277 struct hash_impl<hana::type_tag> {
278 template <typename T>
279 static constexpr T apply(T const& t)
280 { return t; }
281 };
282 }} // end namespace boost::hana
283
284 #endif // !BOOST_HANA_TYPE_HPP