]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/hana/include/boost/hana/fwd/optional.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / hana / include / boost / hana / fwd / optional.hpp
1 /*!
2 @file
3 Forward declares `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_FWD_OPTIONAL_HPP
11 #define BOOST_HANA_FWD_OPTIONAL_HPP
12
13 #include <boost/hana/config.hpp>
14 #include <boost/hana/detail/operators/adl.hpp>
15 #include <boost/hana/fwd/core/make.hpp>
16
17
18 BOOST_HANA_NAMESPACE_BEGIN
19 //! @ingroup group-datatypes
20 //! Optional value whose optional-ness is known at compile-time.
21 //!
22 //! An `optional` either contains a value (represented as `just(x)`), or
23 //! it is empty (represented as `nothing`). In essence, `hana::optional`
24 //! is pretty much like a `boost::optional` or the upcoming `std::optional`,
25 //! except for the fact that whether a `hana::optional` is empty or not is
26 //! known at compile-time. This can be particularly useful for returning
27 //! from a function that might fail, but whose reason for failing is not
28 //! important. Of course, whether the function will fail has to be known
29 //! at compile-time.
30 //!
31 //! This is really an important difference between `hana::optional` and
32 //! `std::optional`. Unlike `std::optional<T>{}` and `std::optional<T>{x}`
33 //! who share the same type (`std::optional<T>`), `hana::just(x)` and
34 //! `hana::nothing` do not share the same type, since the state of the
35 //! optional has to be known at compile-time. Hence, whether a `hana::just`
36 //! or a `hana::nothing` will be returned from a function has to be known
37 //! at compile-time for the return type of that function to be computable
38 //! by the compiler. This makes `hana::optional` well suited for static
39 //! metaprogramming tasks, but very poor for anything dynamic.
40 //!
41 //!
42 //! Interoperation with `type`s
43 //! ---------------------------
44 //! When a `just` contains an object of type `T` which is a `type`,
45 //! it has a nested `::%type` alias equivalent to `T::%type`. `nothing`,
46 //! however, never has a nested `::%type` alias. If `t` is a `type`,
47 //! this allows `decltype(just(t))` to be seen as a nullary metafunction
48 //! equivalent to `decltype(t)`. Along with the `sfinae` function,
49 //! this allows `hana::optional` to interact seamlessly with
50 //! SFINAE-friendly metafunctions.
51 //! Example:
52 //! @include example/optional/sfinae_friendly_metafunctions.cpp
53 //!
54 //!
55 //! Modeled concepts
56 //! ----------------
57 //! 1. `Comparable`\n
58 //! Two `optional`s are equal if and only if they are both empty or they
59 //! both contain a value and those values are equal.
60 //! @include example/optional/comparable.cpp
61 //!
62 //! 2. `Orderable`\n
63 //! Optional values can be ordered by considering the value they are
64 //! holding, if any. To handle the case of an empty optional value, we
65 //! arbitrarily set `nothing` as being less than any other `just`. Hence,
66 //! @code
67 //! just(x) < just(y) if and only if x < y
68 //! nothing < just(anything)
69 //! @endcode
70 //! Example:
71 //! @include example/optional/orderable.cpp
72 //!
73 //! 3. `Functor`\n
74 //! An optional value can be seen as a list containing either one element
75 //! (`just(x)`) or no elements at all (`nothing`). As such, mapping
76 //! a function over an optional value is equivalent to applying it to
77 //! its value if there is one, and to `nothing` otherwise:
78 //! @code
79 //! transform(just(x), f) == just(f(x))
80 //! transform(nothing, f) == nothing
81 //! @endcode
82 //! Example:
83 //! @include example/optional/functor.cpp
84 //!
85 //! 4. `Applicative`\n
86 //! First, a value can be made optional with `lift<optional_tag>`, which
87 //! is equivalent to `just`. Second, one can feed an optional value to an
88 //! optional function with `ap`, which will return `just(f(x))` if there
89 //! is both a function _and_ a value, and `nothing` otherwise:
90 //! @code
91 //! ap(just(f), just(x)) == just(f(x))
92 //! ap(nothing, just(x)) == nothing
93 //! ap(just(f), nothing) == nothing
94 //! ap(nothing, nothing) == nothing
95 //! @endcode
96 //! A simple example:
97 //! @include example/optional/applicative.cpp
98 //! A more complex example:
99 //! @include example/optional/applicative.complex.cpp
100 //!
101 //! 5. `Monad`\n
102 //! The `Monad` model makes it easy to compose actions that might fail.
103 //! One can feed an optional value if there is one into a function with
104 //! `chain`, which will return `nothing` if there is no value. Finally,
105 //! optional-optional values can have their redundant level of optionality
106 //! removed with `flatten`. Also note that the `|` operator can be used in
107 //! place of the `chain` function.
108 //! Example:
109 //! @include example/optional/monad.cpp
110 //!
111 //! 6. `MonadPlus`\n
112 //! The `MonadPlus` model allows choosing the first valid value out of
113 //! two optional values with `concat`. If both optional values are
114 //! `nothing`s, `concat` will return `nothing`.
115 //! Example:
116 //! @include example/optional/monad_plus.cpp
117 //!
118 //! 7. `Foldable`\n
119 //! Folding an optional value is equivalent to folding a list containing
120 //! either no elements (for `nothing`) or `x` (for `just(x)`).
121 //! Example:
122 //! @include example/optional/foldable.cpp
123 //!
124 //! 8. `Searchable`\n
125 //! Searching an optional value is equivalent to searching a list
126 //! containing `x` for `just(x)` and an empty list for `nothing`.
127 //! Example:
128 //! @include example/optional/searchable.cpp
129 #ifdef BOOST_HANA_DOXYGEN_INVOKED
130 template <typename ...T>
131 struct optional {
132 // 5.3.1, Constructors
133
134 //! Default-construct an `optional`. Only exists if the optional
135 //! contains a value, and if that value is DefaultConstructible.
136 constexpr optional() = default;
137
138 //! Copy-construct an `optional`.
139 //! An empty optional may only be copy-constructed from another
140 //! empty `optional`, and an `optional` with a value may only be
141 //! copy-constructed from another `optional` with a value.
142 //! Furthermore, this constructor only exists if the value
143 //! held in the `optional` is CopyConstructible.
144 optional(optional const&) = default;
145
146 //! Move-construct an `optional`.
147 //! An empty optional may only be move-constructed from another
148 //! empty `optional`, and an `optional` with a value may only be
149 //! move-constructed from another `optional` with a value.
150 //! Furthermore, this constructor only exists if the value
151 //! held in the `optional` is MoveConstructible.
152 optional(optional&&) = default;
153
154 //! Construct an `optional` holding a value of type `T` from another
155 //! object of type `T`. The value is copy-constructed.
156 constexpr optional(T const& t)
157 : value_(t)
158 { }
159
160 //! Construct an `optional` holding a value of type `T` from another
161 //! object of type `T`. The value is move-constructed.
162 constexpr optional(T&& t)
163 : value_(static_cast<T&&>(t))
164 { }
165
166 // 5.3.3, Assignment
167
168 //! Copy-assign an `optional`.
169 //! An empty optional may only be copy-assigned from another empty
170 //! `optional`, and an `optional` with a value may only be copy-assigned
171 //! from another `optional` with a value. Furthermore, this assignment
172 //! operator only exists if the value held in the `optional` is
173 //! CopyAssignable.
174 constexpr optional& operator=(optional const&) = default;
175
176 //! Move-assign an `optional`.
177 //! An empty optional may only be move-assigned from another empty
178 //! `optional`, and an `optional` with a value may only be move-assigned
179 //! from another `optional` with a value. Furthermore, this assignment
180 //! operator only exists if the value held in the `optional` is
181 //! MoveAssignable.
182 constexpr optional& operator=(optional&&) = default;
183
184 // 5.3.5, Observers
185
186 //! Returns a pointer to the contained value, or a `nullptr` if the
187 //! `optional` is empty.
188 //!
189 //!
190 //! @note Overloads of this method are provided for both the `const`
191 //! and the non-`const` cases.
192 //!
193 //!
194 //! Example
195 //! -------
196 //! @include example/optional/value.cpp
197 constexpr T* operator->();
198
199 //! Extract the content of an `optional`, or fail at compile-time.
200 //!
201 //! If `*this` contains a value, that value is returned. Otherwise,
202 //! a static assertion is triggered.
203 //!
204 //! @note
205 //! Overloads of this method are provided for the cases where `*this`
206 //! is a reference, a rvalue-reference and their `const` counterparts.
207 //!
208 //!
209 //! Example
210 //! -------
211 //! @include example/optional/value.cpp
212 constexpr T& value();
213
214 //! Equivalent to `value()`, provided for convenience.
215 //!
216 //! @note
217 //! Overloads of this method are provided for the cases where `*this`
218 //! is a reference, a rvalue-reference and their `const` counterparts.
219 //!
220 //!
221 //! Example
222 //! -------
223 //! @include example/optional/value.cpp
224 constexpr T& operator*();
225
226 //! Return the contents of an `optional`, with a fallback result.
227 //!
228 //! If `*this` contains a value, that value is returned. Otherwise,
229 //! the default value provided is returned.
230 //!
231 //! @note
232 //! Overloads of this method are provided for the cases where `*this`
233 //! is a reference, a rvalue-reference and their `const` counterparts.
234 //!
235 //!
236 //! @param default_
237 //! The default value to return if `*this` does not contain a value.
238 //!
239 //!
240 //! Example
241 //! -------
242 //! @include example/optional/value_or.cpp
243 template <typename U>
244 constexpr decltype(auto) value_or(U&& default_);
245
246 //! Equivalent to `hana::chain`.
247 template <typename ...T, typename F>
248 friend constexpr auto operator|(optional<T...>, F);
249
250 //! Equivalent to `hana::equal`
251 template <typename X, typename Y>
252 friend constexpr auto operator==(X&& x, Y&& y);
253
254 //! Equivalent to `hana::not_equal`
255 template <typename X, typename Y>
256 friend constexpr auto operator!=(X&& x, Y&& y);
257
258 //! Equivalent to `hana::less`
259 template <typename X, typename Y>
260 friend constexpr auto operator<(X&& x, Y&& y);
261
262 //! Equivalent to `hana::greater`
263 template <typename X, typename Y>
264 friend constexpr auto operator>(X&& x, Y&& y);
265
266 //! Equivalent to `hana::less_equal`
267 template <typename X, typename Y>
268 friend constexpr auto operator<=(X&& x, Y&& y);
269
270 //! Equivalent to `hana::greater_equal`
271 template <typename X, typename Y>
272 friend constexpr auto operator>=(X&& x, Y&& y);
273 };
274 #else
275 template <typename ...T>
276 struct optional;
277 #endif
278
279 //! Tag representing a `hana::optional`.
280 //! @relates hana::optional
281 struct optional_tag { };
282
283 //! Create an optional value.
284 //! @relates hana::optional
285 //!
286 //! Specifically, `make<optional_tag>()` is equivalent to `nothing`, and
287 //! `make<optional_tag>(x)` is equivalent to `just(x)`. This is provided
288 //! for consistency with the other `make<...>` functions.
289 //!
290 //!
291 //! Example
292 //! -------
293 //! @include example/optional/make.cpp
294 #ifdef BOOST_HANA_DOXYGEN_INVOKED
295 template <>
296 constexpr auto make<optional_tag> = []([auto&& x]) {
297 return optional<std::decay<decltype(x)>::type>{forwarded(x)};
298 };
299 #endif
300
301 //! Alias to `make<optional_tag>`; provided for convenience.
302 //! @relates hana::optional
303 //!
304 //!
305 //! Example
306 //! -------
307 //! @include example/optional/make.cpp
308 constexpr auto make_optional = make<optional_tag>;
309
310 //! Create an optional value containing `x`.
311 //! @relates hana::optional
312 //!
313 //!
314 //! Example
315 //! -------
316 //! @include example/optional/just.cpp
317 #ifdef BOOST_HANA_DOXYGEN_INVOKED
318 constexpr auto just = [](auto&& x) {
319 return optional<std::decay<decltype(x)>::type>{forwarded(x)};
320 };
321 #else
322 struct make_just_t {
323 template <typename T>
324 constexpr auto operator()(T&&) const;
325 };
326
327 constexpr make_just_t just{};
328 #endif
329
330 //! An empty optional value.
331 //! @relates hana::optional
332 //!
333 //!
334 //! Example
335 //! -------
336 //! @include example/optional/nothing.cpp
337 #ifdef BOOST_HANA_DOXYGEN_INVOKED
338 constexpr optional<> nothing{};
339 #else
340 template <>
341 struct optional<> : detail::operators::adl<optional<>> {
342 // 5.3.1, Constructors
343 constexpr optional() = default;
344 constexpr optional(optional const&) = default;
345 constexpr optional(optional&&) = default;
346
347 // 5.3.3, Assignment
348 constexpr optional& operator=(optional const&) = default;
349 constexpr optional& operator=(optional&&) = default;
350
351 // 5.3.5, Observers
352 constexpr decltype(nullptr) operator->() const { return nullptr; }
353
354 template <typename ...dummy>
355 constexpr auto value() const;
356
357 template <typename ...dummy>
358 constexpr auto operator*() const;
359
360 template <typename U>
361 constexpr U&& value_or(U&& u) const;
362 };
363
364 constexpr optional<> nothing{};
365 #endif
366
367 //! Apply a function to the contents of an optional, with a fallback
368 //! result.
369 //! @relates hana::optional
370 //!
371 //! Specifically, `maybe` takes a default value, a function and an
372 //! optional value. If the optional value is `nothing`, the default
373 //! value is returned. Otherwise, the function is applied to the
374 //! content of the `just`.
375 //!
376 //!
377 //! @param default_
378 //! A default value returned if `m` is `nothing`.
379 //!
380 //! @param f
381 //! A function called as `f(x)` if and only if `m` is an optional value
382 //! of the form `just(x)`. In that case, the result returend by `maybe`
383 //! is the result of `f`.
384 //!
385 //! @param m
386 //! An optional value.
387 //!
388 //!
389 //! Example
390 //! -------
391 //! @include example/optional/maybe.cpp
392 #ifdef BOOST_HANA_DOXYGEN_INVOKED
393 constexpr auto maybe = [](auto&& default_, auto&& f, auto&& m) -> decltype(auto) {
394 if (m is a just(x)) {
395 return forwarded(f)(forwarded(x));
396 else
397 return forwarded(default_);
398 }
399 };
400 #else
401 struct maybe_t {
402 template <typename Def, typename F, typename T>
403 constexpr decltype(auto) operator()(Def&&, F&& f, optional<T> const& m) const
404 { return static_cast<F&&>(f)(m.value_); }
405
406 template <typename Def, typename F, typename T>
407 constexpr decltype(auto) operator()(Def&&, F&& f, optional<T>& m) const
408 { return static_cast<F&&>(f)(m.value_); }
409
410 template <typename Def, typename F, typename T>
411 constexpr decltype(auto) operator()(Def&&, F&& f, optional<T>&& m) const
412 { return static_cast<F&&>(f)(static_cast<optional<T>&&>(m).value_); }
413
414 template <typename Def, typename F>
415 constexpr Def operator()(Def&& def, F&&, optional<> const&) const
416 { return static_cast<Def&&>(def); }
417 };
418
419 constexpr maybe_t maybe{};
420 #endif
421
422 //! Calls a function if the call expression is well-formed.
423 //! @relates hana::optional
424 //!
425 //! Given a function `f`, `sfinae` returns a new function applying `f`
426 //! to its arguments and returning `just` the result if the call is
427 //! well-formed, and `nothing` otherwise. In other words, `sfinae(f)(x...)`
428 //! is `just(f(x...))` if that expression is well-formed, and `nothing`
429 //! otherwise. Note, however, that it is possible for an expression
430 //! `f(x...)` to be well-formed as far as SFINAE is concerned, but
431 //! trying to actually compile `f(x...)` still fails. In this case,
432 //! `sfinae` won't be able to detect it and a hard failure is likely
433 //! to happen.
434 //!
435 //!
436 //! @note
437 //! The function given to `sfinae` must not return `void`, since
438 //! `just(void)` does not make sense. A compilation error is
439 //! triggered if the function returns void.
440 //!
441 //!
442 //! Example
443 //! -------
444 //! @include example/optional/sfinae.cpp
445 #ifdef BOOST_HANA_DOXYGEN_INVOKED
446 auto sfinae = [](auto&& f) {
447 return [perfect-capture](auto&& ...x) {
448 if (decltype(forwarded(f)(forwarded(x)...)) is well-formed)
449 return just(forwarded(f)(forwarded(x)...));
450 else
451 return nothing;
452 };
453 };
454 #else
455 struct sfinae_t {
456 template <typename F>
457 constexpr decltype(auto) operator()(F&& f) const;
458 };
459
460 constexpr sfinae_t sfinae{};
461 #endif
462
463 //! Return whether an `optional` contains a value.
464 //! @relates hana::optional
465 //!
466 //! Specifically, returns a compile-time true-valued `Logical` if `m` is
467 //! of the form `just(x)` for some `x`, and a false-valued one otherwise.
468 //!
469 //!
470 //! Example
471 //! -------
472 //! @include example/optional/is_just.cpp
473 #ifdef BOOST_HANA_DOXYGEN_INVOKED
474 constexpr auto is_just = [](auto const& m) {
475 return m is a just(x);
476 };
477 #else
478 struct is_just_t {
479 template <typename ...T>
480 constexpr auto operator()(optional<T...> const&) const;
481 };
482
483 constexpr is_just_t is_just{};
484 #endif
485
486 //! Return whether an `optional` is empty.
487 //! @relates hana::optional
488 //!
489 //! Specifically, returns a compile-time true-valued `Logical` if `m` is
490 //! a `nothing`, and a false-valued one otherwise.
491 //!
492 //!
493 //! Example
494 //! -------
495 //! @include example/optional/is_nothing.cpp
496 #ifdef BOOST_HANA_DOXYGEN_INVOKED
497 constexpr auto is_nothing = [](auto const& m) {
498 return m is a nothing;
499 };
500 #else
501 struct is_nothing_t {
502 template <typename ...T>
503 constexpr auto operator()(optional<T...> const&) const;
504 };
505
506 constexpr is_nothing_t is_nothing{};
507 #endif
508 BOOST_HANA_NAMESPACE_END
509
510 #endif // !BOOST_HANA_FWD_OPTIONAL_HPP