File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/XS/librangeV3.x/i/range/v3/utility/optional.hpp
Criterion Covered Total %
statement 41 41 100.0
branch 5 10 50.0
condition n/a
subroutine n/a
pod n/a
total 46 51 90.2


line stmt bran cond sub pod time code
1             /// \file
2             // Range v3 library
3             //
4             // Copyright Casey Carter 2017
5             //
6             // Use, modification and distribution is subject to the
7             // Boost Software License, Version 1.0. (See accompanying
8             // file LICENSE_1_0.txt or copy at
9             // http://www.boost.org/LICENSE_1_0.txt)
10             //
11             // Project home: https://github.com/ericniebler/range-v3
12             //
13              
14             #ifndef RANGES_V3_UTILITY_OPTIONAL_HPP
15             #define RANGES_V3_UTILITY_OPTIONAL_HPP
16              
17             #include
18             #include
19             #include
20             #include
21             #include
22             #include
23             #include
24             #include
25              
26             namespace ranges
27             {
28             inline namespace v3
29             {
30             /// \ingroup group-utility
31             struct in_place_t {};
32             RANGES_INLINE_VARIABLE(in_place_t, in_place)
33              
34             template struct optional;
35              
36             struct bad_optional_access
37             : std::exception
38             {
39             virtual const char *what() const noexcept override
40             {
41             return "bad optional access";
42             }
43             };
44              
45             struct nullopt_t
46             {
47             struct tag {};
48             explicit constexpr nullopt_t(tag) noexcept {}
49             };
50             #if RANGES_CXX_INLINE_VARIABLES >= RANGES_CXX_INLINE_VARIABLES_17
51             inline constexpr nullopt_t nullopt{nullopt_t::tag{}};
52             #else
53             /// \cond
54             namespace detail
55             {
56             template
57             struct nullopt_holder {
58             static constexpr nullopt_t nullopt{nullopt_t::tag{}};
59             };
60             template
61             constexpr nullopt_t nullopt_holder::nullopt;
62             }
63             /// \endcond
64             inline namespace {
65             constexpr auto &nullopt = detail::nullopt_holder::nullopt;
66             }
67             #endif
68              
69             /// \cond
70             namespace detail
71             {
72             template
73             [[noreturn]] bool throw_bad_optional_access()
74             {
75             throw bad_optional_access{};
76             }
77              
78             namespace optional_adl
79             {
80             template::value>
81             struct optional_storage
82             {
83             union
84             {
85             char dummy_;
86             meta::_t> data_;
87             };
88             bool engaged_;
89              
90 1276           constexpr optional_storage() noexcept
91             : optional_storage(tag{},
92             meta::strict_and<
93             detail::is_trivially_default_constructible,
94 1276           detail::is_trivially_copyable>{})
95 1276           {}
96             template
97             CONCEPT_REQUIRES_(Constructible())>
98 638           constexpr explicit optional_storage(in_place_t, Args &&... args)
99             noexcept(std::is_nothrow_constructible::value)
100 638           : data_(static_cast(args)...), engaged_{true}
101 638           {}
102              
103 1276           RANGES_CXX14_CONSTEXPR void reset() noexcept
104             {
105 1276           engaged_ = false;
106 1276           }
107             private:
108             struct tag {};
109 1276           constexpr optional_storage(tag, std::false_type) noexcept
110 1276           : dummy_{}, engaged_{false}
111 1276           {}
112             constexpr optional_storage(tag, std::true_type) noexcept
113             : data_{}, engaged_{false}
114             {}
115             };
116              
117             template
118             struct optional_storage
119             {
120             union
121             {
122             char dummy_;
123             meta::_t> data_;
124             };
125             bool engaged_;
126              
127             ~optional_storage()
128             {
129             reset();
130             }
131             constexpr optional_storage() noexcept
132             : dummy_{}, engaged_{false}
133             {}
134             template
135             CONCEPT_REQUIRES_(Constructible())>
136             constexpr explicit optional_storage(in_place_t, Args &&... args)
137             noexcept(std::is_nothrow_constructible::value)
138             : data_(static_cast(args)...), engaged_{true}
139             {}
140             optional_storage(optional_storage const &) = default;
141             optional_storage(optional_storage &&) = default;
142             optional_storage &operator=(optional_storage const &) = default;
143             optional_storage &operator=(optional_storage &&) = default;
144              
145             void reset() noexcept
146             {
147             if (engaged_)
148             {
149             data_.~T();
150             engaged_ = false;
151             }
152             }
153             };
154              
155             template
156 2552           struct optional_base
157             : private optional_storage
158             {
159 1276           using optional_storage::optional_storage;
160             using optional_storage::reset;
161              
162 638           constexpr bool has_value() const noexcept
163             {
164 638           return engaged_;
165             }
166 3605           RANGES_CXX14_CONSTEXPR T &operator*() & noexcept
167             {
168 3605 50         return RANGES_EXPECT(engaged_), data_;
    50          
    50          
169             }
170             constexpr T const &operator*() const & noexcept
171             {
172             return RANGES_EXPECT(engaged_), data_;
173             }
174             RANGES_CXX14_CONSTEXPR T &&operator*() && noexcept
175             {
176             return RANGES_EXPECT(engaged_), detail::move(data_);
177             }
178             RANGES_CXX14_CONSTEXPR T const &&operator*() const && noexcept
179             {
180             return RANGES_EXPECT(engaged_), detail::move(data_);
181             }
182             RANGES_CXX14_CONSTEXPR T *operator->() noexcept
183             {
184             return RANGES_EXPECT(engaged_), std::addressof(data_);
185             }
186             constexpr T const *operator->() const noexcept
187             {
188             return RANGES_EXPECT(engaged_), std::addressof(data_);
189             }
190             CONCEPT_REQUIRES(MoveConstructible() && Swappable())
191             RANGES_CXX14_CONSTEXPR void swap(optional_base &that)
192             noexcept(std::is_nothrow_move_constructible::value &&
193             is_nothrow_swappable::value)
194             {
195             constexpr bool can_swap_trivially =
196             !adl_swap_detail::is_adl_swappable_::value &&
197             detail::is_trivially_move_constructible::value &&
198             detail::is_trivially_move_assignable::value;
199              
200             swap_(meta::bool_{}, that);
201             }
202             protected:
203             template
204             CONCEPT_REQUIRES_(Constructible())>
205 319           T &construct_from(Args &&... args)
206             noexcept(std::is_nothrow_constructible::value)
207             {
208 319 50         RANGES_EXPECT(!engaged_);
209 319           auto const address = static_cast(std::addressof(data_));
210 319 50         ::new (address) T(static_cast(args)...);
211 319           engaged_ = true;
212 319           return data_;
213             }
214             template
215             RANGES_CXX14_CONSTEXPR void assign_from(U &&that)
216             noexcept(
217             std::is_nothrow_constructible
218             decltype(*static_cast(that))>::value &&
219             std::is_nothrow_assignable
220             decltype(*static_cast(that))>::value)
221             {
222             if (!that.has_value())
223             reset();
224             else if (engaged_)
225             data_ = *static_cast(that);
226             else
227             {
228             auto const address = static_cast(std::addressof(data_));
229             ::new (address) T(*static_cast(that));
230             engaged_ = true;
231             }
232             }
233             private:
234             RANGES_CXX14_CONSTEXPR
235             void swap_(std::true_type, optional_base &that) noexcept
236             {
237             ranges::swap(
238             static_cast &>(*this),
239             static_cast &>(that));
240             }
241             RANGES_CXX14_CONSTEXPR
242             void swap_(std::false_type, optional_base &that)
243             noexcept(std::is_nothrow_move_constructible::value &&
244             is_nothrow_swappable::value)
245             {
246             if (that.engaged_ == engaged_)
247             {
248             if (engaged_)
249             ranges::swap(data_, that.data_);
250             }
251             else
252             {
253             auto &src = engaged_ ? *this : that;
254             auto &dst = engaged_ ? that : *this;
255             dst.construct_from(detail::move(src.data_));
256             src.reset();
257             }
258             }
259              
260             using optional_storage::engaged_;
261             using optional_storage::data_;
262             };
263              
264             template
265             struct optional_base
266             {
267             optional_base() = default;
268             template
269             CONCEPT_REQUIRES_(Constructible())>
270             constexpr explicit optional_base(in_place_t, Arg &&arg) noexcept
271             : ptr_(std::addressof(arg))
272             {}
273             constexpr bool has_value() const noexcept
274             {
275             return ptr_;
276             }
277             constexpr T &operator*() const noexcept
278             {
279             return RANGES_EXPECT(ptr_), *ptr_;
280             }
281             constexpr T *operator->() const noexcept
282             {
283             return RANGES_EXPECT(ptr_), ptr_;
284             }
285             RANGES_CXX14_CONSTEXPR void reset() noexcept
286             {
287             ptr_ = nullptr;
288             }
289             CONCEPT_REQUIRES(Swappable())
290             RANGES_CXX14_CONSTEXPR void swap(optional_base &that)
291             noexcept(is_nothrow_swappable::value)
292             {
293             if (ptr_ && that.ptr_)
294             ranges::swap(*ptr_, *that.ptr_);
295             else
296             ranges::swap(ptr_, that.ptr_);
297             }
298             protected:
299             template
300             CONCEPT_REQUIRES_(ConvertibleTo())>
301             RANGES_CXX14_CONSTEXPR T &construct_from(U &&ref) noexcept
302             {
303             RANGES_EXPECT(!ptr_);
304             ptr_ = std::addressof(ref);
305             return *ptr_;
306             }
307             template
308             RANGES_CXX14_CONSTEXPR void assign_from(U &&that)
309             {
310             if (ptr_ && that.ptr_)
311             *ptr_ = *that.ptr_;
312             else
313             ptr_ = that.ptr_;
314             }
315             private:
316             T *ptr_ = nullptr;
317             };
318              
319             template
320             struct optional_copy
321             : optional_base
322             {
323             optional_copy() = default;
324             optional_copy(optional_copy const &that)
325             noexcept(std::is_nothrow_copy_constructible::value)
326             {
327             if (that.has_value())
328             this->construct_from(*that);
329             }
330             optional_copy(optional_copy &&) = default;
331             optional_copy &operator=(optional_copy const &) = default;
332             optional_copy &operator=(optional_copy &&) = default;
333              
334             using optional_base::optional_base;
335             };
336              
337             template
338             using copy_construct_layer = meta::if_c<
339             std::is_copy_constructible::value &&
340             !detail::is_trivially_copy_constructible::value,
341             optional_copy, optional_base>;
342              
343             template
344             struct optional_move
345             : copy_construct_layer
346             {
347             optional_move() = default;
348             optional_move(optional_move const &) = default;
349             optional_move(optional_move &&that)
350             noexcept(std::is_nothrow_move_constructible::value)
351             {
352             if (that.has_value())
353             this->construct_from(std::move(*that));
354             }
355             optional_move &operator=(optional_move const &) = default;
356             optional_move &operator=(optional_move &&) = default;
357              
358             using copy_construct_layer::copy_construct_layer;
359             };
360              
361             template
362             using move_construct_layer = meta::if_c<
363             std::is_move_constructible::value &&
364             !detail::is_trivially_move_constructible::value,
365             optional_move, copy_construct_layer>;
366              
367             template
368             struct optional_copy_assign
369             : move_construct_layer
370             {
371             optional_copy_assign() = default;
372             optional_copy_assign(optional_copy_assign const &) = default;
373             optional_copy_assign(optional_copy_assign &&) = default;
374             optional_copy_assign &operator=(optional_copy_assign const &that)
375             noexcept(std::is_nothrow_copy_constructible::value &&
376             std::is_nothrow_copy_assignable::value)
377             {
378             this->assign_from(that);
379             return *this;
380             }
381             optional_copy_assign &operator=(optional_copy_assign &&) = default;
382              
383             using move_construct_layer::move_construct_layer;
384             };
385              
386             template
387             struct deleted_copy_assign
388             : move_construct_layer
389             {
390             deleted_copy_assign() = default;
391             deleted_copy_assign(deleted_copy_assign const &) = default;
392             deleted_copy_assign(deleted_copy_assign &&) = default;
393             deleted_copy_assign &operator=(deleted_copy_assign const &) = delete;
394             deleted_copy_assign &operator=(deleted_copy_assign &&) = default;
395              
396 1276           using move_construct_layer::move_construct_layer;
397             };
398              
399             template
400             using copy_assign_layer = meta::if_c<
401             std::is_copy_constructible::value && std::is_copy_assignable::value,
402             meta::if_c<
403             std::is_reference::value ||
404             !(detail::is_trivially_copy_constructible::value &&
405             detail::is_trivially_copy_assignable::value),
406             optional_copy_assign, move_construct_layer>,
407             deleted_copy_assign>;
408              
409             template
410             struct optional_move_assign
411             : copy_assign_layer
412             {
413             optional_move_assign() = default;
414             optional_move_assign(optional_move_assign const &) = default;
415             optional_move_assign(optional_move_assign &&) = default;
416             optional_move_assign &operator=(optional_move_assign const &) = default;
417             optional_move_assign &operator=(optional_move_assign &&that)
418             noexcept(std::is_nothrow_move_constructible::value &&
419             std::is_nothrow_move_assignable::value)
420             {
421             this->assign_from(std::move(that));
422             return *this;
423             }
424              
425             using copy_assign_layer::copy_assign_layer;
426             };
427              
428             template
429             struct deleted_move_assign
430             : copy_assign_layer
431             {
432             deleted_move_assign() = default;
433             deleted_move_assign(deleted_move_assign const &) = default;
434             deleted_move_assign(deleted_move_assign &&) = default;
435             deleted_move_assign &operator=(deleted_move_assign const &) = default;
436             deleted_move_assign &operator=(deleted_move_assign &&) = delete;
437              
438 1276           using copy_assign_layer::copy_assign_layer;
439             };
440              
441             template
442             using move_assign_layer = meta::if_c<
443             std::is_move_constructible::value && std::is_move_assignable::value,
444             meta::if_c<
445             std::is_reference::value ||
446             !(detail::is_trivially_move_constructible::value &&
447             detail::is_trivially_move_assignable::value),
448             optional_move_assign, copy_assign_layer>,
449             deleted_move_assign>;
450             } // namespace optional_adl
451             } // namespace detail
452             /// \endcond
453              
454             template
455             struct optional
456             : detail::optional_adl::move_assign_layer
457             {
458             private:
459             using base_t = detail::optional_adl::move_assign_layer;
460             public:
461             CONCEPT_ASSERT(Destructible());
462             CONCEPT_ASSERT(std::is_object::value || std::is_lvalue_reference::value);
463             CONCEPT_ASSERT(!Same>());
464             CONCEPT_ASSERT(!Same>());
465             using value_type = meta::_t>;
466              
467 1276           constexpr optional() noexcept
468 1276           {}
469             constexpr optional(nullopt_t) noexcept
470             : optional{}
471             {}
472             optional(optional const &) = default;
473             optional(optional &&) = default;
474              
475             using base_t::base_t;
476              
477             template
478             CONCEPT_REQUIRES_(Constructible &, Args...>())>
479             constexpr explicit optional(in_place_t, std::initializer_list il, Args &&... args)
480             noexcept(std::is_nothrow_constructible &, Args...>::value)
481             : base_t(in_place, il, static_cast(args)...)
482             {}
483              
484             template
485             CONCEPT_REQUIRES_(meta::and_<
486             meta::not_, in_place_t>>,
487             meta::not_, optional>>,
488             Constructible,
489             ConvertibleTo>::value)>
490 638           constexpr optional(U &&v)
491 638           : base_t(in_place, static_cast(v))
492 638           {}
493             template
494             CONCEPT_REQUIRES_(meta::and_<
495             meta::not_, in_place_t>>,
496             meta::not_, optional>>,
497             Constructible,
498             meta::not_>>::value)>
499             explicit constexpr optional(U &&v)
500             : base_t(in_place, static_cast(v))
501             {}
502              
503             template
504             using ShouldConvert = meta::not_
505             Constructible & >,
506             Constructible && >,
507             Constructible const & >,
508             Constructible const &&>,
509             ConvertibleTo &, T>,
510             ConvertibleTo &&, T>,
511             ConvertibleTo const &, T>,
512             ConvertibleTo const &&, T>>>;
513              
514             template
515             CONCEPT_REQUIRES_(meta::and_<
516             ShouldConvert,
517             Constructible,
518             ConvertibleTo>::value)>
519             optional(optional const &that)
520             {
521             if (that.has_value())
522             base_t::construct_from(*that);
523             }
524             template
525             CONCEPT_REQUIRES_(meta::and_<
526             ShouldConvert,
527             Constructible,
528             meta::not_>>::value)>
529             explicit optional(optional const &that)
530             {
531             if (that.has_value())
532             base_t::construct_from(*that);
533             }
534              
535             template
536             CONCEPT_REQUIRES_(meta::and_<
537             ShouldConvert,
538             Constructible,
539             ConvertibleTo>::value)>
540             optional(optional &&that)
541             {
542             if (that.has_value())
543             base_t::construct_from(detail::move(*that));
544             }
545             template
546             CONCEPT_REQUIRES_(meta::and_<
547             ShouldConvert,
548             Constructible,
549             meta::not_>>::value)>
550             explicit optional(optional &&that)
551             {
552             if (that.has_value())
553             base_t::construct_from(detail::move(*that));
554             }
555              
556             RANGES_CXX14_CONSTEXPR
557             optional &operator=(nullopt_t) noexcept
558             {
559             reset();
560             return *this;
561             }
562              
563             optional &operator=(optional const &) = default;
564             optional &operator=(optional &&) = default;
565              
566             template
567             CONCEPT_REQUIRES_(meta::and_<
568             meta::bool_>::value &&
569             !(std::is_scalar::value && std::is_same>::value)>,
570             Constructible,
571             Assignable>::value)>
572             RANGES_CXX14_CONSTEXPR
573             optional &operator=(U &&u)
574             noexcept(std::is_nothrow_constructible::value &&
575             std::is_nothrow_assignable::value)
576             {
577             if (has_value())
578             **this = static_cast(u);
579             else
580             base_t::construct_from(static_cast(u));
581             return *this;
582             }
583              
584             template
585             using ShouldConvertAssign = meta::and_<
586             ShouldConvert,
587             meta::not_
588             Assignable &>,
589             Assignable &&>,
590             Assignable const &>,
591             Assignable const &&>>>>;
592              
593             template
594             CONCEPT_REQUIRES_(meta::and_<
595             ShouldConvertAssign,
596             Constructible,
597             Assignable>::value)>
598             RANGES_CXX14_CONSTEXPR
599             optional &operator=(optional const &that)
600             {
601             base_t::assign_from(that);
602             return *this;
603             }
604              
605             template
606             CONCEPT_REQUIRES_(meta::and_<
607             ShouldConvertAssign,
608             Constructible,
609             Assignable>::value)>
610             RANGES_CXX14_CONSTEXPR
611             optional &operator=(optional &&that)
612             {
613             base_t::assign_from(std::move(that));
614             return *this;
615             }
616              
617             template
618             CONCEPT_REQUIRES_(Constructible())>
619 319           T &emplace(Args &&... args)
620             noexcept(std::is_nothrow_constructible::value)
621             {
622 319           reset();
623 319           return base_t::construct_from(static_cast(args)...);
624             }
625             template
626             CONCEPT_REQUIRES_(Constructible &, Args &&...>())>
627             T &emplace(std::initializer_list il, Args &&... args)
628             noexcept(std::is_nothrow_constructible<
629             T, std::initializer_list &, Args...>::value)
630             {
631             reset();
632             return base_t::construct_from(il, static_cast(args)...);
633             }
634              
635             using base_t::swap;
636             using base_t::operator->;
637             using base_t::operator*;
638              
639 638           constexpr explicit operator bool() const noexcept
640             {
641 638           return has_value();
642             }
643             using base_t::has_value;
644              
645             constexpr T const &value() const &
646             {
647             return (has_value() || detail::throw_bad_optional_access()),
648             **this;
649             }
650             RANGES_CXX14_CONSTEXPR T &value() &
651             {
652             return (has_value() || detail::throw_bad_optional_access()),
653             **this;
654             }
655             constexpr T const &&value() const &&
656             {
657             return (has_value() || detail::throw_bad_optional_access()),
658             detail::move(**this);
659             }
660             RANGES_CXX14_CONSTEXPR T &&value() &&
661             {
662             return (has_value() || detail::throw_bad_optional_access()),
663             detail::move(**this);
664             }
665              
666             template
667             CONCEPT_REQUIRES_(CopyConstructible() && ConvertibleTo())>
668             constexpr T value_or(U &&u) const &
669             {
670             return has_value() ? **this : static_cast((U &&)u);
671             }
672             template
673             CONCEPT_REQUIRES_(MoveConstructible() && ConvertibleTo())>
674             RANGES_CXX14_CONSTEXPR T value_or(U &&u) &&
675             {
676             return has_value() ? detail::move(**this) : static_cast((U &&)u);
677             }
678              
679             using base_t::reset;
680             };
681              
682             /// \cond
683             namespace detail
684             {
685             namespace optional_adl
686             {
687             constexpr bool convert_bool(bool b) noexcept
688             {
689             return b;
690             }
691              
692             // Relational operators [optional.relops]
693             template
694             constexpr auto operator==(optional const &x, optional const &y)
695             noexcept(noexcept(convert_bool(*x == *y))) ->
696             decltype(convert_bool(*x == *y))
697             {
698             return x.has_value() == y.has_value() &&
699             (!x || convert_bool(*x == *y));
700             }
701             template
702             constexpr auto operator!=(optional const &x, optional const &y)
703             noexcept(noexcept(convert_bool(*x != *y))) ->
704             decltype(convert_bool(*x != *y))
705             {
706             return x.has_value() != y.has_value() ||
707             (x && convert_bool(*x != *y));
708             }
709             template
710             constexpr auto operator<(optional const &x, optional const &y)
711             noexcept(noexcept(convert_bool(*x < *y))) ->
712             decltype(convert_bool(*x < *y))
713             {
714             return y && (!x || convert_bool(*x < *y));
715             }
716             template
717             constexpr auto operator>(optional const &x, optional const &y)
718             noexcept(noexcept(convert_bool(*x > *y))) ->
719             decltype(convert_bool(*x > *y))
720             {
721             return x && (!y || convert_bool(*x > *y));
722             }
723             template
724             constexpr auto operator<=(optional const &x, optional const &y)
725             noexcept(noexcept(convert_bool(*x <= *y))) ->
726             decltype(convert_bool(*x <= *y))
727             {
728             return !x || (y && convert_bool(*x <= *y));
729             }
730             template
731             constexpr auto operator>=(optional const &x, optional const &y)
732             noexcept(noexcept(convert_bool(*x >= *y))) ->
733             decltype(convert_bool(*x >= *y))
734             {
735             return !y || (x && convert_bool(*x >= *y));
736             }
737              
738             // Comparisons with nullopt [optional.nullops]
739             template
740             constexpr bool operator==(optional const &x, nullopt_t) noexcept
741             {
742             return !x;
743             }
744             template
745             constexpr bool operator==(nullopt_t, optional const &x) noexcept
746             {
747             return !x;
748             }
749             template
750             constexpr bool operator!=(optional const &x, nullopt_t) noexcept
751             {
752             return !!x;
753             }
754             template
755             constexpr bool operator!=(nullopt_t, optional const &x) noexcept
756             {
757             return !!x;
758             }
759             template
760             constexpr bool operator<(optional const &, nullopt_t) noexcept
761             {
762             return false;
763             }
764             template
765             constexpr bool operator<(nullopt_t, optional const &x) noexcept
766             {
767             return !!x;
768             }
769             template
770             constexpr bool operator>(optional const &x, nullopt_t) noexcept
771             {
772             return !!x;
773             }
774             template
775             constexpr bool operator>(nullopt_t, optional const &) noexcept
776             {
777             return false;
778             }
779             template
780             constexpr bool operator<=(optional const &x, nullopt_t) noexcept
781             {
782             return !x;
783             }
784             template
785             constexpr bool operator<=(nullopt_t, optional const &) noexcept
786             {
787             return true;
788             }
789             template
790             constexpr bool operator>=(optional const &, nullopt_t) noexcept
791             {
792             return true;
793             }
794             template
795             constexpr bool operator>=(nullopt_t, optional const &x) noexcept
796             {
797             return !x;
798             }
799              
800             // Comparisons with T [optional.comp_with_t]
801             template
802             constexpr auto operator==(optional const &x, U const &y)
803             noexcept(noexcept(convert_bool(*x == y))) ->
804             decltype(convert_bool(*x == y))
805             {
806             return x && convert_bool(*x == y);
807             }
808             template
809             constexpr auto operator==(T const &x, optional const &y)
810             noexcept(noexcept(convert_bool(x == *y))) ->
811             decltype(convert_bool(x == *y))
812             {
813             return y && convert_bool(x == *y);
814             }
815             template
816             constexpr auto operator!=(optional const &x, U const &y)
817             noexcept(noexcept(convert_bool(*x != y))) ->
818             decltype(convert_bool(*x != y))
819             {
820             return !x || convert_bool(*x != y);
821             }
822             template
823             constexpr auto operator!=(T const &x, optional const &y)
824             noexcept(noexcept(convert_bool(x != *y))) ->
825             decltype(convert_bool(x != *y))
826             {
827             return !y || convert_bool(x != *y);
828             }
829             template
830             constexpr auto operator<(optional const &x, U const &y)
831             noexcept(noexcept(convert_bool(*x < y))) ->
832             decltype(convert_bool(*x < y))
833             {
834             return !x || convert_bool(*x < y);
835             }
836             template
837             constexpr auto operator<(T const &x, optional const &y)
838             noexcept(noexcept(convert_bool(x < *y))) ->
839             decltype(convert_bool(x < *y))
840             {
841             return y && convert_bool(x < *y);
842             }
843             template
844             constexpr auto operator>(optional const &x, U const &y)
845             noexcept(noexcept(convert_bool(*x > y))) ->
846             decltype(convert_bool(*x > y))
847             {
848             return x && convert_bool(*x > y);
849             }
850             template
851             constexpr auto operator>(T const &x, optional const &y)
852             noexcept(noexcept(convert_bool(x > *y))) ->
853             decltype(convert_bool(x > *y))
854             {
855             return !y || convert_bool(x > *y);
856             }
857             template
858             constexpr auto operator<=(optional const &x, U const &y)
859             noexcept(noexcept(convert_bool(*x <= y))) ->
860             decltype(convert_bool(*x <= y))
861             {
862             return !x || convert_bool(*x <= y);
863             }
864             template
865             constexpr auto operator<=(T const &x, optional const &y)
866             noexcept(noexcept(convert_bool(x <= *y))) ->
867             decltype(convert_bool(x <= *y))
868             {
869             return y && convert_bool(x <= *y);
870             }
871             template
872             constexpr auto operator>=(optional const &x, U const &y)
873             noexcept(noexcept(convert_bool(*x >= y))) ->
874             decltype(convert_bool(*x >= y))
875             {
876             return x && convert_bool(*x >= y);
877             }
878             template
879             constexpr auto operator>=(T const &x, optional const &y)
880             noexcept(noexcept(convert_bool(x >= *y))) ->
881             decltype(convert_bool(x >= *y))
882             {
883             return !y || convert_bool(x >= *y);
884             }
885              
886             template
887             auto swap(optional &x, optional &y)
888             RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
889             (
890             x.swap(y)
891             )
892             } // namespace optional_adl
893             } // namespace detail
894             /// \endcond
895              
896             template
897             constexpr auto make_optional(T &&t)
898             RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
899             (
900             optional>{static_cast(t)}
901             )
902             template
903             constexpr auto make_optional(Args &&... args)
904             RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
905             (
906             optional{in_place, static_cast(args)...}
907             )
908             template
909             constexpr auto make_optional(std::initializer_list il, Args &&... args)
910             RANGES_DECLTYPE_AUTO_RETURN_NOEXCEPT
911             (
912             optional{in_place, il, static_cast(args)...}
913             )
914              
915             /// \cond
916             namespace detail
917             {
918             template
919             struct non_propagating_cache
920             : optional
921             {
922 638           non_propagating_cache() = default;
923             constexpr non_propagating_cache(nullopt_t) noexcept
924             {}
925             constexpr
926             non_propagating_cache(non_propagating_cache const &) noexcept
927             : optional{}
928             {}
929             RANGES_CXX14_CONSTEXPR
930 957           non_propagating_cache(non_propagating_cache &&that) noexcept
931 957           : optional{}
932             {
933 957           that.optional::reset();
934 957           }
935             RANGES_CXX14_CONSTEXPR
936             non_propagating_cache &operator=(non_propagating_cache const &) noexcept
937             {
938             optional::reset();
939             return *this;
940             }
941             RANGES_CXX14_CONSTEXPR
942             non_propagating_cache &operator=(non_propagating_cache &&that) noexcept
943             {
944             that.optional::reset();
945             optional::reset();
946             return *this;
947             }
948             using optional::operator=;
949             };
950              
951             template
952             struct non_propagating_cache
953             {};
954             } // namespace detail
955             /// \endcond
956             } // namespace v3
957             } // namespace ranges
958              
959             #endif