]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/hana/include/boost/hana/optional.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / hana / include / boost / hana / optional.hpp
1 /*!
2 @file
3 Defines `boost::hana::optional`.
4
5 @copyright Louis Dionne 2013-2016
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_OPTIONAL_HPP
11 #define BOOST_HANA_OPTIONAL_HPP
12
13 #include <boost/hana/fwd/optional.hpp>
14
15 #include <boost/hana/bool.hpp>
16 #include <boost/hana/config.hpp>
17 #include <boost/hana/core/tag_of.hpp>
18 #include <boost/hana/detail/decay.hpp>
19 #include <boost/hana/detail/operators/adl.hpp>
20 #include <boost/hana/detail/operators/comparable.hpp>
21 #include <boost/hana/detail/operators/monad.hpp>
22 #include <boost/hana/detail/operators/orderable.hpp>
23 #include <boost/hana/detail/wrong.hpp>
24 #include <boost/hana/functional/partial.hpp>
25 #include <boost/hana/fwd/any_of.hpp>
26 #include <boost/hana/fwd/ap.hpp>
27 #include <boost/hana/fwd/concat.hpp>
28 #include <boost/hana/fwd/core/make.hpp>
29 #include <boost/hana/fwd/empty.hpp>
30 #include <boost/hana/fwd/equal.hpp>
31 #include <boost/hana/fwd/find_if.hpp>
32 #include <boost/hana/fwd/flatten.hpp>
33 #include <boost/hana/fwd/less.hpp>
34 #include <boost/hana/fwd/lift.hpp>
35 #include <boost/hana/fwd/transform.hpp>
36 #include <boost/hana/fwd/type.hpp>
37 #include <boost/hana/fwd/unpack.hpp>
38
39 #include <cstddef> // std::nullptr_t
40 #include <type_traits>
41 #include <utility>
42
43
44 BOOST_HANA_NAMESPACE_BEGIN
45 //////////////////////////////////////////////////////////////////////////
46 // optional<>
47 //////////////////////////////////////////////////////////////////////////
48 namespace detail {
49 template <typename T, typename = typename hana::tag_of<T>::type>
50 struct nested_type { };
51
52 template <typename T>
53 struct nested_type<T, type_tag> { using type = typename T::type; };
54 }
55
56 template <typename T>
57 struct optional<T> : detail::operators::adl<>, detail::nested_type<T> {
58 // 5.3.1, Constructors
59 constexpr optional() = default;
60 constexpr optional(optional const&) = default;
61 constexpr optional(optional&&) = default;
62
63 constexpr optional(T const& t)
64 : value_(t)
65 { }
66
67 constexpr optional(T&& t)
68 : value_(static_cast<T&&>(t))
69 { }
70
71 // 5.3.3, Assignment
72 constexpr optional& operator=(optional const&) = default;
73 constexpr optional& operator=(optional&&) = default;
74
75 // 5.3.5, Observers
76 constexpr T const* operator->() const { return &value_; }
77 constexpr T* operator->() { return &value_; }
78
79 constexpr T& value() & { return value_; }
80 constexpr T const& value() const& { return value_; }
81 constexpr T&& value() && { return static_cast<T&&>(value_); }
82 constexpr T const&& value() const&& { return static_cast<T const&&>(value_); }
83
84 constexpr T& operator*() & { return value_; }
85 constexpr T const& operator*() const& { return value_; }
86 constexpr T&& operator*() && { return static_cast<T&&>(value_); }
87 constexpr T const&& operator*() const&& { return static_cast<T const&&>(value_); }
88
89 template <typename U> constexpr T& value_or(U&&) & { return value_; }
90 template <typename U> constexpr T const& value_or(U&&) const& { return value_; }
91 template <typename U> constexpr T&& value_or(U&&) && { return static_cast<T&&>(value_); }
92 template <typename U> constexpr T const&& value_or(U&&) const&& { return static_cast<T const&&>(value_); }
93
94 // We leave this public because it simplifies the implementation, but
95 // this should be considered private by users.
96 T value_;
97 };
98
99 //! @cond
100 template <typename ...dummy>
101 constexpr auto optional<>::value() const {
102 static_assert(detail::wrong<dummy...>{},
103 "hana::optional::value() requires a non-empty optional");
104 }
105
106 template <typename ...dummy>
107 constexpr auto optional<>::operator*() const {
108 static_assert(detail::wrong<dummy...>{},
109 "hana::optional::operator* requires a non-empty optional");
110 }
111
112 template <typename U>
113 constexpr U&& optional<>::value_or(U&& u) const {
114 return static_cast<U&&>(u);
115 }
116
117 template <typename T>
118 constexpr auto make_just_t::operator()(T&& t) const {
119 return hana::optional<typename detail::decay<T>::type>(static_cast<T&&>(t));
120 }
121 //! @endcond
122
123 template <typename ...T>
124 struct tag_of<optional<T...>> {
125 using type = optional_tag;
126 };
127
128 //////////////////////////////////////////////////////////////////////////
129 // make<optional_tag>
130 //////////////////////////////////////////////////////////////////////////
131 template <>
132 struct make_impl<optional_tag> {
133 template <typename X>
134 static constexpr auto apply(X&& x)
135 { return hana::just(static_cast<X&&>(x)); }
136
137 static constexpr auto apply()
138 { return hana::nothing; }
139 };
140
141 //////////////////////////////////////////////////////////////////////////
142 // Operators
143 //////////////////////////////////////////////////////////////////////////
144 namespace detail {
145 template <>
146 struct comparable_operators<optional_tag> {
147 static constexpr bool value = true;
148 };
149 template <>
150 struct orderable_operators<optional_tag> {
151 static constexpr bool value = true;
152 };
153 template <>
154 struct monad_operators<optional_tag> {
155 static constexpr bool value = true;
156 };
157 }
158
159 //////////////////////////////////////////////////////////////////////////
160 // is_just and is_nothing
161 //////////////////////////////////////////////////////////////////////////
162 //! @cond
163 template <typename ...T>
164 constexpr auto is_just_t::operator()(optional<T...> const&) const
165 { return hana::bool_c<sizeof...(T) != 0>; }
166
167 template <typename ...T>
168 constexpr auto is_nothing_t::operator()(optional<T...> const&) const
169 { return hana::bool_c<sizeof...(T) == 0>; }
170 //! @endcond
171
172 //////////////////////////////////////////////////////////////////////////
173 // sfinae
174 //////////////////////////////////////////////////////////////////////////
175 namespace detail {
176 struct sfinae_impl {
177 template <typename F, typename ...X, typename = decltype(
178 std::declval<F>()(std::declval<X>()...)
179 )>
180 constexpr decltype(auto) operator()(int, F&& f, X&& ...x) const {
181 using Return = decltype(static_cast<F&&>(f)(static_cast<X&&>(x)...));
182 static_assert(!std::is_same<Return, void>::value,
183 "hana::sfinae(f)(args...) requires f(args...) to be non-void");
184
185 return hana::just(static_cast<F&&>(f)(static_cast<X&&>(x)...));
186 }
187
188 template <typename F, typename ...X>
189 constexpr auto operator()(long, F&&, X&& ...) const
190 { return hana::nothing; }
191 };
192 }
193
194 //! @cond
195 template <typename F>
196 constexpr decltype(auto) sfinae_t::operator()(F&& f) const {
197 return hana::partial(detail::sfinae_impl{}, int{},
198 static_cast<F&&>(f));
199 }
200 //! @endcond
201
202 //////////////////////////////////////////////////////////////////////////
203 // Comparable
204 //////////////////////////////////////////////////////////////////////////
205 template <>
206 struct equal_impl<optional_tag, optional_tag> {
207 template <typename T, typename U>
208 static constexpr auto apply(hana::optional<T> const& t, hana::optional<U> const& u)
209 { return hana::equal(t.value_, u.value_); }
210
211 static constexpr hana::true_ apply(hana::optional<> const&, hana::optional<> const&)
212 { return {}; }
213
214 template <typename T, typename U>
215 static constexpr hana::false_ apply(T const&, U const&)
216 { return {}; }
217 };
218
219 //////////////////////////////////////////////////////////////////////////
220 // Orderable
221 //////////////////////////////////////////////////////////////////////////
222 template <>
223 struct less_impl<optional_tag, optional_tag> {
224 template <typename T>
225 static constexpr hana::true_ apply(hana::optional<> const&, hana::optional<T> const&)
226 { return {}; }
227
228 static constexpr hana::false_ apply(hana::optional<> const&, hana::optional<> const&)
229 { return {}; }
230
231 template <typename T>
232 static constexpr hana::false_ apply(hana::optional<T> const&, hana::optional<> const&)
233 { return {}; }
234
235 template <typename T, typename U>
236 static constexpr auto apply(hana::optional<T> const& x, hana::optional<U> const& y)
237 { return hana::less(x.value_, y.value_); }
238 };
239
240 //////////////////////////////////////////////////////////////////////////
241 // Functor
242 //////////////////////////////////////////////////////////////////////////
243 template <>
244 struct transform_impl<optional_tag> {
245 template <typename F>
246 static constexpr auto apply(optional<> const&, F&&)
247 { return hana::nothing; }
248
249 template <typename T, typename F>
250 static constexpr auto apply(optional<T> const& opt, F&& f)
251 { return hana::just(static_cast<F&&>(f)(opt.value_)); }
252
253 template <typename T, typename F>
254 static constexpr auto apply(optional<T>& opt, F&& f)
255 { return hana::just(static_cast<F&&>(f)(opt.value_)); }
256
257 template <typename T, typename F>
258 static constexpr auto apply(optional<T>&& opt, F&& f)
259 { return hana::just(static_cast<F&&>(f)(static_cast<T&&>(opt.value_))); }
260 };
261
262 //////////////////////////////////////////////////////////////////////////
263 // Applicative
264 //////////////////////////////////////////////////////////////////////////
265 template <>
266 struct lift_impl<optional_tag> {
267 template <typename X>
268 static constexpr auto apply(X&& x)
269 { return hana::just(static_cast<X&&>(x)); }
270 };
271
272 template <>
273 struct ap_impl<optional_tag> {
274 template <typename F, typename X>
275 static constexpr auto ap_helper(F&&, X&&, ...)
276 { return hana::nothing; }
277
278 template <typename F, typename X>
279 static constexpr auto ap_helper(F&& f, X&& x, hana::true_, hana::true_)
280 { return hana::just(static_cast<F&&>(f).value_(static_cast<X&&>(x).value_)); }
281
282 template <typename F, typename X>
283 static constexpr auto apply(F&& f, X&& x) {
284 return ap_impl::ap_helper(static_cast<F&&>(f), static_cast<X&&>(x),
285 hana::is_just(f), hana::is_just(x));
286 }
287 };
288
289 //////////////////////////////////////////////////////////////////////////
290 // Monad
291 //////////////////////////////////////////////////////////////////////////
292 template <>
293 struct flatten_impl<optional_tag> {
294 static constexpr auto apply(optional<> const&)
295 { return hana::nothing; }
296
297 static constexpr auto apply(optional<optional<>> const&)
298 { return hana::nothing; }
299
300 template <typename T>
301 static constexpr auto apply(optional<optional<T>> const& opt)
302 { return hana::just(opt.value_.value_); }
303
304 template <typename T>
305 static constexpr auto apply(optional<optional<T>>&& opt)
306 { return hana::just(static_cast<T&&>(opt.value_.value_)); }
307 };
308
309 //////////////////////////////////////////////////////////////////////////
310 // MonadPlus
311 //////////////////////////////////////////////////////////////////////////
312 template <>
313 struct concat_impl<optional_tag> {
314 template <typename Y>
315 static constexpr auto apply(hana::optional<>&, Y&& y)
316 { return static_cast<Y&&>(y); }
317
318 template <typename Y>
319 static constexpr auto apply(hana::optional<>&&, Y&& y)
320 { return static_cast<Y&&>(y); }
321
322 template <typename Y>
323 static constexpr auto apply(hana::optional<> const&, Y&& y)
324 { return static_cast<Y&&>(y); }
325
326 template <typename X, typename Y>
327 static constexpr auto apply(X&& x, Y&&)
328 { return static_cast<X&&>(x); }
329 };
330
331 template <>
332 struct empty_impl<optional_tag> {
333 static constexpr auto apply()
334 { return hana::nothing; }
335 };
336
337 //////////////////////////////////////////////////////////////////////////
338 // Foldable
339 //////////////////////////////////////////////////////////////////////////
340 template <>
341 struct unpack_impl<optional_tag> {
342 template <typename T, typename F>
343 static constexpr decltype(auto) apply(optional<T>&& opt, F&& f)
344 { return static_cast<F&&>(f)(static_cast<T&&>(opt.value_)); }
345
346 template <typename T, typename F>
347 static constexpr decltype(auto) apply(optional<T> const& opt, F&& f)
348 { return static_cast<F&&>(f)(opt.value_); }
349
350 template <typename T, typename F>
351 static constexpr decltype(auto) apply(optional<T>& opt, F&& f)
352 { return static_cast<F&&>(f)(opt.value_); }
353
354 template <typename F>
355 static constexpr decltype(auto) apply(optional<> const&, F&& f)
356 { return static_cast<F&&>(f)(); }
357 };
358
359 //////////////////////////////////////////////////////////////////////////
360 // Searchable
361 //////////////////////////////////////////////////////////////////////////
362 namespace detail {
363 template <bool>
364 struct optional_find_if {
365 template <typename T>
366 static constexpr auto apply(T const&)
367 { return hana::nothing; }
368 };
369
370 template <>
371 struct optional_find_if<true> {
372 template <typename T>
373 static constexpr auto apply(T&& t)
374 { return hana::just(static_cast<T&&>(t)); }
375 };
376 }
377
378 template <>
379 struct find_if_impl<optional_tag> {
380 template <typename T, typename Pred>
381 static constexpr auto apply(hana::optional<T> const& opt, Pred&& pred) {
382 constexpr bool found = decltype(static_cast<Pred&&>(pred)(opt.value_))::value;
383 return detail::optional_find_if<found>::apply(opt.value_);
384 }
385
386 template <typename T, typename Pred>
387 static constexpr auto apply(hana::optional<T>& opt, Pred&& pred) {
388 constexpr bool found = decltype(static_cast<Pred&&>(pred)(opt.value_))::value;
389 return detail::optional_find_if<found>::apply(opt.value_);
390 }
391
392 template <typename T, typename Pred>
393 static constexpr auto apply(hana::optional<T>&& opt, Pred&& pred) {
394 constexpr bool found = decltype(
395 static_cast<Pred&&>(pred)(static_cast<T&&>(opt.value_))
396 )::value;
397 return detail::optional_find_if<found>::apply(static_cast<T&&>(opt.value_));
398 }
399
400 template <typename Pred>
401 static constexpr auto apply(hana::optional<> const&, Pred&&)
402 { return hana::nothing; }
403 };
404
405 template <>
406 struct any_of_impl<optional_tag> {
407 template <typename T, typename Pred>
408 static constexpr auto apply(hana::optional<T> const& opt, Pred&& pred)
409 { return static_cast<Pred&&>(pred)(opt.value_); }
410
411 template <typename Pred>
412 static constexpr hana::false_ apply(hana::optional<> const&, Pred&&)
413 { return {}; }
414 };
415 BOOST_HANA_NAMESPACE_END
416
417 #endif // !BOOST_HANA_OPTIONAL_HPP