2 * Copyright 2017 Jacob Lifshay
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 #ifndef UTIL_OPTIONAL_H_
25 #define UTIL_OPTIONAL_H_
27 #include <type_traits>
30 #include <initializer_list>
36 #include "is_swappable.h"
44 constexpr explicit nullopt_t(int)
49 constexpr nullopt_t
nullopt(0);
51 class bad_optional_access
: public std::exception
54 virtual const char *what() const noexcept override
56 return "bad_optional_access";
63 bool Is_Trivially_Destructible
= std::is_trivially_destructible
<T
>::value
,
64 bool Is_Trivially_Copyable
= std::is_trivially_copyable
<T
>::value
>
70 alignas(T
) char empty_value
[sizeof(T
)];
73 constexpr Optional_base() noexcept
: empty_value
{}, is_full(false)
76 constexpr Optional_base(nullopt_t
) noexcept
: empty_value
{}, is_full(false)
85 template <typename
... Types
>
86 T
&emplace(Types
&&... args
) noexcept(std::is_nothrow_constructible
<T
, Types
...>::value
)
89 ::new(static_cast<void *>(std::addressof(full_value
))) T(std::forward
<Types
>(args
)...);
96 typename
= typename
std::
97 enable_if
<std::is_constructible
<T
, std::initializer_list
<U
>, Types
...>::value
>::type
>
98 T
&emplace(std::initializer_list
<U
> init_list
, Types
&&... args
) noexcept(
99 std::is_nothrow_constructible
<T
, std::initializer_list
<U
>, Types
...>::value
)
102 ::new(static_cast<void *>(std::addressof(full_value
)))
103 T(init_list
, std::forward
<Types
>(args
)...);
107 Optional_base(const Optional_base
&rt
) noexcept(std::is_nothrow_copy_constructible
<T
>::value
)
108 : empty_value
{}, is_full(false)
111 emplace(rt
.full_value
);
113 Optional_base(Optional_base
&&rt
) noexcept(std::is_nothrow_move_constructible
<T
>::value
)
114 : empty_value
{}, is_full(false)
117 emplace(std::move(rt
.full_value
));
119 template <typename
... Types
,
120 typename
= typename
std::enable_if
<std::is_constructible
<T
, Types
...>::value
>::type
>
121 constexpr explicit Optional_base(in_place_t
, Types
&&... args
) noexcept(
122 std::is_nothrow_constructible
<T
, Types
...>::value
)
123 : full_value(std::forward
<Types
>(args
)...), is_full(true)
129 typename
= typename
std::
130 enable_if
<std::is_constructible
<T
, std::initializer_list
<U
>, Types
...>::value
>::type
>
131 constexpr explicit Optional_base(
133 std::initializer_list
<U
> init_list
,
134 Types
&&... args
) noexcept(std::is_nothrow_constructible
<T
, Types
...>::value
)
135 : full_value(init_list
, std::forward
<Types
>(args
)...), is_full(true)
142 Optional_base
&operator=(const Optional_base
&rt
) noexcept(
143 std::is_nothrow_copy_assignable
<T
>::value
)
148 emplace(rt
.full_value
);
150 full_value
= rt
.full_value
;
153 Optional_base
&operator=(Optional_base
&&rt
) noexcept(std::is_nothrow_move_assignable
<T
>::value
)
158 emplace(std::move(rt
.full_value
));
160 full_value
= std::move(rt
.full_value
);
165 template <typename T
>
166 struct Optional_base
<T
, true, false>
171 alignas(T
) char empty_value
[sizeof(T
)];
174 constexpr Optional_base() noexcept
: empty_value
{}, is_full(false)
177 constexpr Optional_base(nullopt_t
) noexcept
: empty_value
{}, is_full(false)
180 void reset() noexcept
182 // full_value.~T() not needed
185 template <typename
... Types
>
186 T
&emplace(Types
&&... args
) noexcept(std::is_nothrow_constructible
<T
, Types
...>::value
)
189 ::new(static_cast<void *>(std::addressof(full_value
))) T(std::forward
<Types
>(args
)...);
196 typename
= typename
std::
197 enable_if
<std::is_constructible
<T
, std::initializer_list
<U
>, Types
...>::value
>::type
>
198 T
&emplace(std::initializer_list
<U
> init_list
, Types
&&... args
) noexcept(
199 std::is_nothrow_constructible
<T
, std::initializer_list
<U
>, Types
...>::value
)
202 ::new(static_cast<void *>(std::addressof(full_value
)))
203 T(init_list
, std::forward
<Types
>(args
)...);
207 Optional_base(const Optional_base
&rt
) noexcept(std::is_nothrow_copy_constructible
<T
>::value
)
208 : empty_value
{}, is_full(false)
211 emplace(rt
.full_value
);
213 Optional_base(Optional_base
&&rt
) noexcept(std::is_nothrow_move_constructible
<T
>::value
)
214 : empty_value
{}, is_full(false)
217 emplace(std::move(rt
.full_value
));
219 template <typename
... Types
,
220 typename
= typename
std::enable_if
<std::is_constructible
<T
, Types
...>::value
>::type
>
221 constexpr explicit Optional_base(in_place_t
, Types
&&... args
) noexcept(
222 std::is_nothrow_constructible
<T
, Types
...>::value
)
223 : full_value(std::forward
<Types
>(args
)...), is_full(true)
229 typename
= typename
std::
230 enable_if
<std::is_constructible
<T
, std::initializer_list
<U
>, Types
...>::value
>::type
>
231 constexpr explicit Optional_base(
233 std::initializer_list
<U
> init_list
,
234 Types
&&... args
) noexcept(std::is_nothrow_constructible
<T
, Types
...>::value
)
235 : full_value(init_list
, std::forward
<Types
>(args
)...), is_full(true)
238 ~Optional_base() = default;
239 Optional_base
&operator=(const Optional_base
&rt
) noexcept(
240 std::is_nothrow_copy_assignable
<T
>::value
)
245 emplace(rt
.full_value
);
247 full_value
= rt
.full_value
;
250 Optional_base
&operator=(Optional_base
&&rt
) noexcept(std::is_nothrow_move_assignable
<T
>::value
)
255 emplace(std::move(rt
.full_value
));
257 full_value
= std::move(rt
.full_value
);
262 template <typename T
>
263 struct Optional_base
<T
, true, true>
268 alignas(T
) char empty_value
[sizeof(T
)];
271 constexpr Optional_base() noexcept
: empty_value
{}, is_full(false)
274 constexpr Optional_base(nullopt_t
) noexcept
: empty_value
{}, is_full(false)
277 void reset() noexcept
279 // full_value.~T() not needed
282 template <typename
... Types
>
283 T
&emplace(Types
&&... args
) noexcept(std::is_nothrow_constructible
<T
, Types
...>::value
)
286 ::new(static_cast<void *>(std::addressof(full_value
))) T(std::forward
<Types
>(args
)...);
293 typename
= typename
std::
294 enable_if
<std::is_constructible
<T
, std::initializer_list
<U
>, Types
...>::value
>::type
>
295 T
&emplace(std::initializer_list
<U
> init_list
, Types
&&... args
) noexcept(
296 std::is_nothrow_constructible
<T
, std::initializer_list
<U
>, Types
...>::value
)
299 ::new(static_cast<void *>(std::addressof(full_value
)))
300 T(init_list
, std::forward
<Types
>(args
)...);
304 constexpr Optional_base(const Optional_base
&rt
) noexcept
= default;
305 constexpr Optional_base(Optional_base
&&rt
) noexcept
= default;
306 template <typename
... Types
,
307 typename
= typename
std::enable_if
<std::is_constructible
<T
, Types
...>::value
>::type
>
308 constexpr explicit Optional_base(in_place_t
, Types
&&... args
) noexcept(
309 std::is_nothrow_constructible
<T
, Types
...>::value
)
310 : full_value(std::forward
<Types
>(args
)...), is_full(true)
316 typename
= typename
std::
317 enable_if
<std::is_constructible
<T
, std::initializer_list
<U
>, Types
...>::value
>::type
>
318 constexpr explicit Optional_base(
320 std::initializer_list
<U
> init_list
,
321 Types
&&... args
) noexcept(std::is_nothrow_constructible
<T
, Types
...>::value
)
322 : full_value(init_list
, std::forward
<Types
>(args
)...), is_full(true)
325 ~Optional_base() = default;
326 Optional_base
&operator=(const Optional_base
&rt
) noexcept
= default;
327 Optional_base
&operator=(Optional_base
&&rt
) noexcept
= default;
331 template <typename T
>
336 template <typename T
, typename U
, typename U_Ref
>
337 constexpr bool optional_needs_conversion_constructors() noexcept
339 if(!std::is_constructible
<T
, U_Ref
>::value
)
341 if(std::is_constructible
<T
, optional
<U
> &>::value
)
343 if(std::is_constructible
<T
, const optional
<U
> &>::value
)
345 if(std::is_constructible
<T
, optional
<U
> &&>::value
)
347 if(std::is_constructible
<T
, const optional
<U
> &&>::value
)
349 if(std::is_convertible
<optional
<U
> &, T
>::value
)
351 if(std::is_convertible
<const optional
<U
> &, T
>::value
)
353 if(std::is_convertible
<optional
<U
> &&, T
>::value
)
355 if(std::is_convertible
<const optional
<U
> &&, T
>::value
)
360 template <typename T
, typename U
, typename U_Ref
>
361 constexpr bool optional_needs_conversion_from_optional_assign_operators() noexcept
363 if(!std::is_constructible
<T
, U_Ref
>::value
)
365 if(!std::is_assignable
<T
&, U_Ref
>::value
)
367 if(std::is_constructible
<T
, optional
<U
> &>::value
)
369 if(std::is_constructible
<T
, const optional
<U
> &>::value
)
371 if(std::is_constructible
<T
, optional
<U
> &&>::value
)
373 if(std::is_constructible
<T
, const optional
<U
> &&>::value
)
375 if(std::is_convertible
<optional
<U
> &, T
>::value
)
377 if(std::is_convertible
<const optional
<U
> &, T
>::value
)
379 if(std::is_convertible
<optional
<U
> &&, T
>::value
)
381 if(std::is_convertible
<const optional
<U
> &&, T
>::value
)
383 if(std::is_assignable
<T
&, optional
<U
> &>::value
)
385 if(std::is_assignable
<T
&, const optional
<U
> &>::value
)
387 if(std::is_assignable
<T
&, optional
<U
> &&>::value
)
389 if(std::is_assignable
<T
&, const optional
<U
> &&>::value
)
395 template <typename T
>
396 class optional
: private detail::Optional_base
<T
>
399 typedef detail::Optional_base
<T
> Base
;
401 using Base::full_value
;
407 constexpr optional() noexcept
= default;
408 constexpr optional(const optional
&) noexcept(std::is_nothrow_copy_constructible
<T
>::value
) =
410 constexpr optional(optional
&&) noexcept(std::is_nothrow_move_constructible
<T
>::value
) =
412 template <typename U
,
413 typename
= typename
std::
414 enable_if
<detail::optional_needs_conversion_constructors
<T
, U
, const U
&>()
415 && std::is_convertible
<const U
&, T
>::value
>::type
>
416 optional(const optional
<U
> &rt
) noexcept(std::is_nothrow_constructible
<T
, const U
&>::value
)
422 template <typename U
,
423 typename
= typename
std::
424 enable_if
<detail::optional_needs_conversion_constructors
<T
, U
, const U
&>()
425 && !std::is_convertible
<const U
&, T
>::value
>::type
,
427 explicit optional(const optional
<U
> &rt
) noexcept(
428 std::is_nothrow_constructible
<T
, const U
&>::value
)
437 typename
std::enable_if
<detail::optional_needs_conversion_constructors
<T
, U
, U
&&>()
438 && std::is_convertible
<U
&&, T
>::value
>::type
>
439 optional(optional
<U
> &&rt
) noexcept(std::is_nothrow_constructible
<T
, U
&&>::value
)
443 emplace(std::move(*rt
));
448 typename
std::enable_if
<detail::optional_needs_conversion_constructors
<T
, U
, U
&&>()
449 && !std::is_convertible
<U
&&, T
>::value
>::type
,
451 explicit optional(optional
<U
> &&rt
) noexcept(std::is_nothrow_constructible
<T
, U
&&>::value
)
455 emplace(std::move(*rt
));
457 template <typename U
,
458 typename
= typename
std::
459 enable_if
<std::is_constructible
<T
, U
&&>::value
460 && !std::is_same
<typename
std::decay
<U
>::type
, in_place_t
>::value
461 && !std::is_same
<typename
std::decay
<U
>::type
, optional
>::value
462 && std::is_convertible
<U
&&, T
>::value
>::type
,
464 constexpr optional(U
&&value
) noexcept(std::is_nothrow_constructible
<T
, U
&&>::value
)
465 : Base(in_place
, std::forward
<U
>(value
))
468 template <typename U
,
469 typename
= typename
std::
470 enable_if
<std::is_constructible
<T
, U
&&>::value
471 && !std::is_same
<typename
std::decay
<U
>::type
, in_place_t
>::value
472 && !std::is_same
<typename
std::decay
<U
>::type
, optional
>::value
473 && !std::is_convertible
<U
&&, T
>::value
>::type
>
474 explicit constexpr optional(U
&&value
) noexcept(std::is_nothrow_constructible
<T
, U
&&>::value
)
475 : Base(in_place
, std::forward
<U
>(value
))
478 constexpr optional
&operator=(const optional
&) noexcept(
479 std::is_nothrow_copy_assignable
<T
>::value
) = default;
480 constexpr optional
&operator=(optional
&&) noexcept(std::is_nothrow_move_assignable
<T
>::value
) =
482 template <typename U
= T
,
483 typename
= typename
std::
484 enable_if
<!std::is_same
<typename
std::decay
<U
>::type
, optional
>::value
485 && std::is_constructible
<T
, U
>::value
486 && std::is_assignable
<T
&, U
>::value
487 && (!std::is_scalar
<T
>::value
488 || !std::is_same
<typename
std::decay
<U
>::type
, T
>::value
)>::type
>
489 optional
&operator=(U
&&value
) noexcept(std::is_nothrow_constructible
<T
, U
&&>::value
490 &&std::is_nothrow_assignable
<T
&, U
&&>::value
)
493 full_value
= std::forward
<U
>(value
);
495 emplace(std::forward
<U
>(value
));
498 optional
&operator=(nullopt_t
) noexcept
505 typename
= typename
std::enable_if
< //
506 detail::optional_needs_conversion_from_optional_assign_operators
<T
, U
, const U
&>()>::
508 optional
&operator=(const optional
<U
> &rt
) noexcept(
509 std::is_nothrow_constructible
<T
, const U
&>::value
510 &&std::is_nothrow_assignable
<T
&, const U
&>::value
)
522 typename
= typename
std::enable_if
< //
523 detail::optional_needs_conversion_from_optional_assign_operators
<T
, U
, U
&&>()>::type
>
524 optional
&operator=(optional
<U
> &&rt
) noexcept(std::is_nothrow_constructible
<T
, U
&&>::value
&&
525 std::is_nothrow_assignable
<T
&, U
&&>::value
)
530 emplace(std::move(*rt
));
532 full_value
= std::move(*rt
);
535 constexpr const T
*operator->() const noexcept
538 return std::addressof(full_value
);
540 constexpr T
*operator->() noexcept
543 return std::addressof(full_value
);
545 constexpr const T
&operator*() const &noexcept
550 constexpr T
&operator*() & noexcept
555 constexpr const T
&&operator*() const &&noexcept
558 return std::move(full_value
);
560 constexpr T
&&operator*() && noexcept
563 return std::move(full_value
);
565 constexpr explicit operator bool() const noexcept
569 constexpr bool has_value() const noexcept
573 constexpr T
&value() &
576 throw bad_optional_access();
579 constexpr const T
&value() const &
582 throw bad_optional_access();
585 constexpr T
&&value() &&
588 throw bad_optional_access();
589 return std::move(full_value
);
591 constexpr const T
&&value() const &&
594 throw bad_optional_access();
595 return std::move(full_value
);
597 template <typename U
>
598 constexpr T
value_or(U
&&default_value
) const &noexcept(
599 std::is_nothrow_copy_constructible
<T
>::value
//
600 &&noexcept(static_cast<T
>(std::declval
<U
>())))
602 return is_full
? full_value
: static_cast<T
>(std::forward
<U
>(default_value
));
604 template <typename U
>
605 constexpr T
value_or(U
&&default_value
)
606 && noexcept(std::is_nothrow_copy_constructible
<T
>::value
//
607 &&noexcept(static_cast<T
>(std::declval
<U
>())))
609 return is_full
? std::move(full_value
) : static_cast<T
>(std::forward
<U
>(default_value
));
611 void swap(optional
&other
) noexcept(
612 std::is_nothrow_move_constructible
<T
>::value
&&util::is_nothrow_swappable
<T
>::value
)
619 swap(full_value
, other
.full_value
);
623 other
.emplace(std::move(full_value
));
627 else if(other
.is_full
)
629 emplace(std::move(other
.full_value
));
635 template <typename T
, typename U
>
636 constexpr bool operator==(const optional
<T
> &l
, const optional
<U
> &r
) noexcept(noexcept(*l
== *r
))
638 if(!l
.has_value() || !r
.has_value())
639 return !r
.has_value();
643 template <typename T
, typename U
>
644 constexpr bool operator!=(const optional
<T
> &l
, const optional
<U
> &r
) noexcept(noexcept(*l
== *r
))
646 if(!l
.has_value() || !r
.has_value())
647 return r
.has_value();
651 template <typename T
, typename U
>
652 constexpr bool operator<(const optional
<T
> &l
, const optional
<U
> &r
) noexcept(noexcept(*l
== *r
))
654 if(!l
.has_value() || !r
.has_value())
655 return r
.has_value();
659 template <typename T
, typename U
>
660 constexpr bool operator>(const optional
<T
> &l
, const optional
<U
> &r
) noexcept(noexcept(*l
== *r
))
662 if(!l
.has_value() || !r
.has_value())
663 return l
.has_value();
667 template <typename T
, typename U
>
668 constexpr bool operator<=(const optional
<T
> &l
, const optional
<U
> &r
) noexcept(noexcept(*l
== *r
))
670 if(!l
.has_value() || !r
.has_value())
671 return !l
.has_value();
675 template <typename T
, typename U
>
676 constexpr bool operator>=(const optional
<T
> &l
, const optional
<U
> &r
) noexcept(noexcept(*l
== *r
))
678 if(!l
.has_value() || !r
.has_value())
679 return !r
.has_value();
683 template <typename T
>
684 constexpr bool operator==(const optional
<T
> &v
, nullopt_t
) noexcept
686 return !v
.has_value();
689 template <typename T
>
690 constexpr bool operator!=(const optional
<T
> &v
, nullopt_t
) noexcept
692 return v
.has_value();
695 template <typename T
>
696 constexpr bool operator<(const optional
<T
> &v
, nullopt_t
) noexcept
701 template <typename T
>
702 constexpr bool operator>(const optional
<T
> &v
, nullopt_t
) noexcept
704 return v
.has_value();
707 template <typename T
>
708 constexpr bool operator<=(const optional
<T
> &v
, nullopt_t
) noexcept
710 return !v
.has_value();
713 template <typename T
>
714 constexpr bool operator>=(const optional
<T
> &v
, nullopt_t
) noexcept
719 template <typename T
>
720 constexpr bool operator==(nullopt_t
, const optional
<T
> &v
) noexcept
722 return !v
.has_value();
725 template <typename T
>
726 constexpr bool operator!=(nullopt_t
, const optional
<T
> &v
) noexcept
728 return v
.has_value();
731 template <typename T
>
732 constexpr bool operator<(nullopt_t
, const optional
<T
> &v
) noexcept
734 return v
.has_value();
737 template <typename T
>
738 constexpr bool operator>(nullopt_t
, const optional
<T
> &v
) noexcept
743 template <typename T
>
744 constexpr bool operator<=(nullopt_t
, const optional
<T
> &v
) noexcept
749 template <typename T
>
750 constexpr bool operator>=(nullopt_t
, const optional
<T
> &v
) noexcept
752 return !v
.has_value();
755 template <typename T
, typename U
>
756 constexpr bool operator==(const optional
<T
> &l
, const U
&r
) noexcept(
757 noexcept(static_cast<bool>(std::declval
<const T
&>() == std::declval
<const U
&>())))
764 template <typename T
, typename U
>
765 constexpr bool operator==(const U
&l
, const optional
<T
> &r
) noexcept(
766 noexcept(static_cast<bool>(std::declval
<const U
&>() == std::declval
<const T
&>())))
773 template <typename T
, typename U
>
774 constexpr bool operator!=(const optional
<T
> &l
, const U
&r
) noexcept(
775 noexcept(static_cast<bool>(std::declval
<const T
&>() != std::declval
<const U
&>())))
782 template <typename T
, typename U
>
783 constexpr bool operator!=(const U
&l
, const optional
<T
> &r
) noexcept(
784 noexcept(static_cast<bool>(std::declval
<const U
&>() != std::declval
<const T
&>())))
791 template <typename T
, typename U
>
792 constexpr bool operator<(const optional
<T
> &l
, const U
&r
) noexcept(
793 noexcept(static_cast<bool>(std::declval
<const T
&>() < std::declval
<const U
&>())))
800 template <typename T
, typename U
>
801 constexpr bool operator<(const U
&l
, const optional
<T
> &r
) noexcept(
802 noexcept(static_cast<bool>(std::declval
<const U
&>() < std::declval
<const T
&>())))
809 template <typename T
, typename U
>
810 constexpr bool operator>(const optional
<T
> &l
, const U
&r
) noexcept(
811 noexcept(static_cast<bool>(std::declval
<const T
&>() > std::declval
<const U
&>())))
818 template <typename T
, typename U
>
819 constexpr bool operator>(const U
&l
, const optional
<T
> &r
) noexcept(
820 noexcept(static_cast<bool>(std::declval
<const U
&>() > std::declval
<const T
&>())))
827 template <typename T
, typename U
>
828 constexpr bool operator<=(const optional
<T
> &l
, const U
&r
) noexcept(
829 noexcept(static_cast<bool>(std::declval
<const T
&>() <= std::declval
<const U
&>())))
836 template <typename T
, typename U
>
837 constexpr bool operator<=(const U
&l
, const optional
<T
> &r
) noexcept(
838 noexcept(static_cast<bool>(std::declval
<const U
&>() <= std::declval
<const T
&>())))
845 template <typename T
, typename U
>
846 constexpr bool operator>=(const optional
<T
> &l
, const U
&r
) noexcept(
847 noexcept(static_cast<bool>(std::declval
<const T
&>() >= std::declval
<const U
&>())))
854 template <typename T
, typename U
>
855 constexpr bool operator>=(const U
&l
, const optional
<T
> &r
) noexcept(
856 noexcept(static_cast<bool>(std::declval
<const U
&>() >= std::declval
<const T
&>())))
863 template <typename T
>
864 constexpr optional
<typename
std::decay
<T
>::type
> make_optional(T
&&value
)
866 return optional
<typename
std::decay
<T
>::type
>(in_place
, std::forward
<T
>(value
));
869 template <typename T
, typename
... Args
>
870 constexpr optional
<T
> make_optional(Args
&&... args
)
872 return optional
<T
>(in_place
, std::forward
<T
>(args
)...);
875 template <typename T
, typename U
, typename
... Args
>
876 constexpr optional
<T
> make_optional(std::initializer_list
<U
> init_list
, Args
&&... args
)
878 return optional
<T
>(in_place
, init_list
, std::forward
<T
>(args
)...);
881 template <typename T
,
882 typename
= typename
std::enable_if
<std::is_move_constructible
<T
>::value
883 && is_swappable
<T
>::value
>::type
>
884 void swap(optional
<T
> &l
, optional
<T
> &r
) noexcept(noexcept(l
.swap(r
)))
891 template <typename T
, bool Is_Enabled
= std::is_default_constructible
<std::hash
<T
>>::value
>
894 constexpr std::size_t operator()(const optional
<T
> &value
) const
895 noexcept(noexcept(static_cast<std::size_t>(std::hash
<T
>()(std::declval
<const T
&>()))))
898 return std::hash
<T
>()(*value
);
903 template <typename T
>
904 struct optional_hash
<T
, false>
906 optional_hash() noexcept
= delete;
907 ~optional_hash() = delete;
908 optional_hash(const optional_hash
&) noexcept
= delete;
909 optional_hash
&operator=(const optional_hash
&) noexcept
= delete;
910 std::size_t operator()(const optional
<T
> &value
) const noexcept
= delete;
918 template <typename T
>
919 struct hash
<kazan::util::optional
<T
>> : public kazan::util::detail::optional_hash
<T
>
924 #endif /* UTIL_OPTIONAL_H_ */