21#if defined(BSONCXX_POLY_USE_STD)
31using std::make_optional;
40#elif defined(BSONCXX_POLY_USE_IMPLS)
49#include <initializer_list>
65BSONCXX_PRIVATE_WARNINGS_PUSH();
66BSONCXX_PRIVATE_WARNINGS_DISABLE(Clang(
"-Wweak-vtables"));
69class bad_optional_access :
public std::exception {
71 char const* what() const noexcept
override {
72 return "bad_optional_access()";
75BSONCXX_PRIVATE_WARNINGS_POP();
79 explicit constexpr nullopt_t(std::nullptr_t)
noexcept {}
83static constexpr nullopt_t nullopt{
nullptr};
86static constexpr struct in_place_t {
92[[noreturn]]
inline void terminate_disengaged_optional(
char const* what)
noexcept {
93 (void)std::fprintf(stderr,
"%s: Invalid attempted use of disengaged optional<T>\n", what);
98[[noreturn]]
inline void throw_bad_optional() {
99 throw bad_optional_access();
104struct optional_base_class;
108std::true_type not_an_optional_f(T
const&);
112std::false_type not_an_optional_f(optional<T>
const&);
116struct not_an_optional : decltype(not_an_optional_f(std::declval<T const&>())){};
118template <
typename T,
typename Ucvr,
typename U>
119struct enable_opt_conversion : bsoncxx::detail::conjunction<
120 std::is_constructible<T, Ucvr>,
121 bsoncxx::detail::disjunction<
122 std::is_same<T, bool>,
123 bsoncxx::detail::negation<bsoncxx::detail::conjunction<
124 std::is_constructible<T, optional<U>&>,
125 std::is_constructible<T, optional<U> const&>,
126 std::is_constructible<T, optional<U>&&>,
127 std::is_constructible<T, optional<U> const&&>,
128 std::is_convertible<optional<U>&, T>,
129 std::is_convertible<optional<U> const&, T>,
130 std::is_convertible<optional<U>&&, T>,
131 std::is_convertible<optional<U> const&&, T>>>>> {};
133template <
typename From,
typename To>
134struct enable_opt_value_conversion : bsoncxx::detail::conjunction<
135 std::is_constructible<To, From&&>,
136 bsoncxx::detail::negation<bsoncxx::detail::is_alike<From, in_place_t>>,
137 bsoncxx::detail::negation<bsoncxx::detail::is_alike<From, optional<To>>>,
138 bsoncxx::detail::disjunction<
139 bsoncxx::detail::negation<bsoncxx::detail::is_alike<To, bool>>,
140 detail::not_an_optional<bsoncxx::detail::remove_cvref_t<From>>>> {};
145class optional : bsoncxx::detail::equality_operators,
146 bsoncxx::detail::ordering_operators,
147 public detail::optional_base_class<T>
::type {
149 using value_type = T;
150 using reference = bsoncxx::detail::add_lvalue_reference_t<T>;
151 using const_reference = bsoncxx::detail::add_lvalue_reference_t<bsoncxx::detail::add_const_t<T>>;
152 using rvalue_reference = bsoncxx::detail::add_rvalue_reference_t<T>;
153 using const_rvalue_reference = bsoncxx::detail::add_rvalue_reference_t<bsoncxx::detail::add_const_t<T>>;
154 using pointer = bsoncxx::detail::add_pointer_t<T>;
155 using const_pointer = bsoncxx::detail::add_pointer_t<T const>;
159 optional() =
default;
160 constexpr optional(nullopt_t)
noexcept {}
164 optional(optional
const&) =
default;
165 optional(optional&&) =
default;
169 optional& operator=(optional
const&) =
default;
170 optional& operator=(optional&&) =
default;
171 ~optional() =
default;
175 template <
typename... Args>
176 BSONCXX_PRIVATE_CONSTEXPR_CXX14
explicit optional(in_place_t, Args&&... args)
noexcept(
177 noexcept(T(BSONCXX_PRIVATE_FWD(args)...))) {
178 this->emplace(BSONCXX_PRIVATE_FWD(args)...);
181 template <
typename U,
typename... Args>
182 BSONCXX_PRIVATE_CONSTEXPR_CXX14
explicit optional(in_place_t, std::initializer_list<U> il, Args&&... args)
noexcept(
183 noexcept(T(il, BSONCXX_PRIVATE_FWD(args)...))) {
184 this->emplace(il, BSONCXX_PRIVATE_FWD(args)...);
191 bsoncxx::detail::requires_t<
193 detail::enable_opt_value_conversion<U&&, T>,
194 bsoncxx::detail::negation<std::is_convertible<U&&, T>>> = 0>
195 BSONCXX_PRIVATE_CONSTEXPR_CXX14
explicit optional(U&& arg)
noexcept(std::is_nothrow_constructible<T, U&&>::value)
196 : optional(in_place, BSONCXX_PRIVATE_FWD(arg)) {}
202 bsoncxx::detail::requires_t<int, detail::enable_opt_value_conversion<U&&, T>, std::is_convertible<U&&, T>> = 0>
203 BSONCXX_PRIVATE_CONSTEXPR_CXX14 optional(U&& arg)
noexcept(std::is_nothrow_constructible<T, U&&>::value)
204 : optional(in_place, BSONCXX_PRIVATE_FWD(arg)) {}
208 bsoncxx::detail::requires_t<
210 detail::enable_opt_conversion<T, U const&, U>,
211 bsoncxx::detail::negation<std::is_convertible<U const&, T>>> = 0>
212 BSONCXX_PRIVATE_CONSTEXPR_CXX14
explicit optional(optional<U>
const& other)
noexcept(
213 std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<U const>>::value) {
214 if (other.has_value()) {
215 this->emplace(*other);
221 bsoncxx::detail::requires_t<
223 detail::enable_opt_conversion<T, U const&, U>,
224 std::is_convertible<U const&, T>> = 0>
225 BSONCXX_PRIVATE_CONSTEXPR_CXX14 optional(optional<U>
const& other)
noexcept(
226 std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<U const>>::value) {
227 if (other.has_value()) {
228 this->emplace(*other);
234 bsoncxx::detail::requires_t<
236 detail::enable_opt_conversion<T, U&&, U>,
237 bsoncxx::detail::negation<std::is_convertible<U&&, T>>> = 0>
238 BSONCXX_PRIVATE_CONSTEXPR_CXX14
explicit optional(optional<U>&& other)
noexcept(
239 std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<U&&>>::value) {
240 if (other.has_value()) {
241 this->emplace(*BSONCXX_PRIVATE_FWD(other));
247 bsoncxx::detail::requires_t<int, detail::enable_opt_conversion<T, U&&, U>, std::is_convertible<U&&, T>> = 0>
248 BSONCXX_PRIVATE_CONSTEXPR_CXX14 optional(optional<U>&& other)
noexcept(
249 std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<U&&>>::value) {
250 if (other.has_value()) {
251 this->emplace(*BSONCXX_PRIVATE_FWD(other));
255 constexpr bool has_value() const noexcept {
256 return this->_has_value;
258 constexpr explicit operator bool() const noexcept {
259 return this->has_value();
264 BSONCXX_PRIVATE_CONSTEXPR_CXX14 reference operator*() &
noexcept {
265 _assert_has_value(
"operator*() &");
266 return this->_storage.value;
268 BSONCXX_PRIVATE_CONSTEXPR_CXX14 const_reference operator*() const& noexcept {
269 _assert_has_value(
"operator*() const&");
270 return this->_storage.value;
272 BSONCXX_PRIVATE_CONSTEXPR_CXX14 rvalue_reference operator*() &&
noexcept {
273 _assert_has_value(
"operator*() &&");
274 return static_cast<rvalue_reference
>(**this);
276 BSONCXX_PRIVATE_CONSTEXPR_CXX14 const_rvalue_reference operator*() const&& noexcept {
277 _assert_has_value(
"operator*() const&&");
278 return static_cast<const_rvalue_reference
>(**this);
283 BSONCXX_PRIVATE_CONSTEXPR_CXX14 pointer operator->() noexcept {
284 _assert_has_value(
"operator->()");
285 return std::addressof(**
this);
287 BSONCXX_PRIVATE_CONSTEXPR_CXX14 const_pointer operator->() const noexcept {
288 _assert_has_value(
"operator->() const");
289 return std::addressof(**
this);
294 BSONCXX_PRIVATE_CONSTEXPR_CXX14 reference value() & {
298 BSONCXX_PRIVATE_CONSTEXPR_CXX14 const_reference value() const& {
302 BSONCXX_PRIVATE_CONSTEXPR_CXX14 rvalue_reference value() && {
304 return static_cast<rvalue_reference
>(**this);
306 BSONCXX_PRIVATE_CONSTEXPR_CXX14 const_rvalue_reference value() const&& {
308 return static_cast<const_rvalue_reference
>(**this);
313 template <
typename U>
314 BSONCXX_PRIVATE_CONSTEXPR_CXX14 value_type value_or(U&& dflt)
const& {
318 return static_cast<value_type
>(BSONCXX_PRIVATE_FWD(dflt));
322 template <
typename U>
323 BSONCXX_PRIVATE_CONSTEXPR_CXX14 value_type value_or(U&& dflt) && {
325 return *std::move(*
this);
327 return static_cast<value_type
>(BSONCXX_PRIVATE_FWD(dflt));
332 BSONCXX_PRIVATE_CONSTEXPR_CXX14
void _assert_has_value(
char const* msg)
const noexcept {
333 if (!this->has_value()) {
334 detail::terminate_disengaged_optional(msg);
338 BSONCXX_PRIVATE_CONSTEXPR_CXX14
void _throw_if_empty()
const {
339 if (!this->has_value()) {
340 detail::throw_bad_optional();
350 std::is_nothrow_constructible<bsoncxx::detail::decay_t<T>, T&&>::value) {
358template <
typename T,
typename... Args>
359BSONCXX_PRIVATE_CONSTEXPR_CXX14
optional<T> make_optional(Args&&... args)
noexcept(
360 std::is_nothrow_constructible<T, Args&&...>::value) {
361 return optional<T>(in_place, BSONCXX_PRIVATE_FWD(args)...);
366template <
typename T,
typename U,
typename... Args>
367BSONCXX_PRIVATE_CONSTEXPR_CXX14
optional<T> make_optional(std::initializer_list<U> il, Args&&... args)
noexcept(
368 std::is_nothrow_constructible<T, std::initializer_list<U>, Args&&...>::value) {
369 return optional<T>(in_place, il, BSONCXX_PRIVATE_FWD(args)...);
375template <typename T, bool = std::is_trivially_destructible<T>::value>
383 storage_for() noexcept : nothing(0) {}
388 storage_for(storage_for
const&) =
delete;
389 storage_for& operator=(storage_for
const&) =
delete;
393union storage_for<T, true > {
396 storage_for() noexcept : nothing(0) {}
397 storage_for(storage_for
const&) =
delete;
398 storage_for& operator=(storage_for
const&) =
delete;
402enum copymove_classification {
411 bool CanCopy = std::is_copy_constructible<T>::value,
412 bool CanMove = std::is_move_constructible<T>::value>
413constexpr copymove_classification classify_construct() {
414 return CanCopy ? copyable : CanMove ? movable : immobile;
420 bool CanCopy = std::is_copy_assignable<T>::value,
421 bool CanMove = std::is_move_assignable<T>::value>
422constexpr copymove_classification classify_assignment() {
423 return CanCopy ? copyable : CanMove ? movable : immobile;
430class optional_common_base;
433template <typename T, copymove_classification = classify_construct<T>()>
434struct optional_construct_base;
437template <typename T, copymove_classification = classify_assignment<T>()>
438struct optional_assign_base;
440template <
bool TrivialDestruct>
441struct optional_destruct_helper;
444using optional_destruct_base =
445 typename optional_destruct_helper<std::is_trivially_destructible<T>::value>::template base<T>;
448struct optional_assign_base<T, copyable> : optional_construct_base<T> {};
451struct optional_assign_base<T, movable> : optional_construct_base<T> {
454 optional_assign_base() =
default;
455 optional_assign_base(optional_assign_base
const&) =
default;
456 optional_assign_base(optional_assign_base&&) =
default;
457 ~optional_assign_base() =
default;
461 BSONCXX_PRIVATE_CONSTEXPR_CXX14 optional_assign_base& operator=(optional_assign_base
const&) =
delete;
465 BSONCXX_PRIVATE_CONSTEXPR_CXX14 optional_assign_base& operator=(optional_assign_base&&) =
default;
469struct optional_assign_base<T, immobile> : optional_construct_base<T> {
470 optional_assign_base() =
default;
471 optional_assign_base(optional_assign_base
const&) =
default;
472 optional_assign_base(optional_assign_base&&) =
default;
473 ~optional_assign_base() =
default;
476 optional_assign_base& operator=(optional_assign_base
const&) =
delete;
477 optional_assign_base& operator=(optional_assign_base&&) =
delete;
481struct optional_construct_base<T, copyable> : optional_destruct_base<T> {};
484struct optional_construct_base<T, movable> : optional_destruct_base<T> {
485 optional_construct_base() =
default;
487 optional_construct_base(optional_construct_base
const&) =
delete;
488 optional_construct_base(optional_construct_base&&) =
default;
489 optional_construct_base& operator=(optional_construct_base
const&) =
default;
490 optional_construct_base& operator=(optional_construct_base&&) =
default;
494struct optional_construct_base<T, immobile> : optional_destruct_base<T> {
495 optional_construct_base() =
default;
496 optional_construct_base(optional_construct_base
const&) =
delete;
497 optional_construct_base& operator=(optional_construct_base
const&) =
default;
498 optional_construct_base& operator=(optional_construct_base&&) =
default;
502struct optional_destruct_helper<false > {
503 template <
typename T>
504 struct base : optional_common_base<T> {
508 base(base
const&) =
default;
509 base(base&&) =
default;
510 base& operator=(base
const&) =
default;
511 base& operator=(base&&) =
default;
521struct optional_destruct_helper<true > {
524 template <
typename T>
525 using base = optional_common_base<T>;
529struct optional_operators_base {
530 template <
typename T,
typename U>
531 friend BSONCXX_PRIVATE_CONSTEXPR_CXX14
auto
532 tag_invoke(bsoncxx::detail::equal_to, optional<T>
const& left, optional<U>
const& right)
noexcept
533 -> bsoncxx::detail::requires_t<bool, bsoncxx::detail::is_equality_comparable<T, U>> {
534 if (left.has_value() != right.has_value()) {
538 BSONCXX_PRIVATE_WARNINGS_PUSH();
539 BSONCXX_PRIVATE_WARNINGS_DISABLE(GNU(
"-Wfloat-equal"));
540 return !left.has_value() || *left == *right;
541 BSONCXX_PRIVATE_WARNINGS_POP();
544 template <
typename T,
typename U>
545 friend constexpr auto tag_invoke(bsoncxx::detail::equal_to, optional<T>
const& left, U
const& right)
noexcept
546 -> bsoncxx::detail::requires_t<bool, not_an_optional<U>, bsoncxx::detail::is_equality_comparable<T, U>> {
547 BSONCXX_PRIVATE_WARNINGS_PUSH();
548 BSONCXX_PRIVATE_WARNINGS_DISABLE(GNU(
"-Wfloat-equal"));
549 return left.has_value() && *left == right;
550 BSONCXX_PRIVATE_WARNINGS_POP();
553 template <
typename T>
554 friend constexpr bool tag_invoke(bsoncxx::detail::equal_to, optional<T>
const& opt, nullopt_t)
noexcept {
555 return !opt.has_value();
558 template <
typename T,
typename U>
559 BSONCXX_PRIVATE_CONSTEXPR_CXX14
friend auto
560 tag_invoke(bsoncxx::detail::compare_three_way compare, optional<T>
const& left, optional<U>
const& right)
561 -> bsoncxx::detail::requires_t<
562 bsoncxx::detail::strong_ordering,
563 bsoncxx::detail::is_totally_ordered_with<T, U>> {
564 if (left.has_value()) {
565 if (right.has_value()) {
566 return compare(*left, *right);
569 return bsoncxx::detail::strong_ordering::greater;
572 if (right.has_value()) {
574 return bsoncxx::detail::strong_ordering::less;
577 return bsoncxx::detail::strong_ordering::equal;
582 template <
typename T,
typename U>
583 BSONCXX_PRIVATE_CONSTEXPR_CXX14
friend auto
584 tag_invoke(bsoncxx::detail::compare_three_way compare, optional<T>
const& left, U
const& right)
585 -> bsoncxx::detail::requires_t<
586 bsoncxx::detail::strong_ordering,
588 bsoncxx::detail::is_totally_ordered_with<T, U>> {
589 if (left.has_value()) {
590 return compare(*left, right);
593 return bsoncxx::detail::strong_ordering::less;
596 template <
typename T>
597 constexpr friend bsoncxx::detail::strong_ordering
598 tag_invoke(bsoncxx::detail::compare_three_way compare, optional<T>
const& left, nullopt_t) {
599 return compare(left.has_value(),
false);
604template <typename T, bool IsSwappable = bsoncxx::detail::is_swappable<T>::value>
605struct optional_swap_mixin {};
608struct optional_swap_mixin<T, true> {
609 BSONCXX_PRIVATE_CONSTEXPR_CXX14
friend void swap(optional<T>& left, optional<T>& right)
noexcept(
610 std::is_nothrow_move_constructible<T>::value && bsoncxx::detail::is_nothrow_swappable<T>::value) {
617class optional_common_base : optional_operators_base, optional_swap_mixin<T> {
618 using storage_type = detail::storage_for<bsoncxx::detail::remove_const_t<T>>;
621 optional_common_base() =
default;
622 ~optional_common_base() =
default;
624 optional_common_base(optional_common_base
const& other)
noexcept(std::is_nothrow_copy_constructible<T>::value) {
625 if (other._has_value) {
626 this->emplace(other._storage.value);
630 optional_common_base(optional_common_base&& other)
noexcept(std::is_nothrow_move_constructible<T>::value) {
631 if (other._has_value) {
632 this->_emplace_construct_anew(std::move(other)._storage.value);
636 optional_common_base& operator=(optional_common_base
const& other)
noexcept(
637 std::is_nothrow_copy_assignable<T>::value) {
638 this->_assign(BSONCXX_PRIVATE_FWD(other));
642 optional_common_base& operator=(optional_common_base&& other)
noexcept(std::is_nothrow_move_assignable<T>::value) {
643 this->_assign(BSONCXX_PRIVATE_FWD(other));
648 void reset() noexcept {
649 if (this->_has_value) {
650 this->_storage.value.~T();
652 this->_has_value =
false;
657 template <
typename... Args>
658 T& emplace(Args&&... args) {
660 this->_emplace_construct_anew(BSONCXX_PRIVATE_FWD(args)...);
661 return this->_storage.value;
666 template <
typename U,
typename... Args>
667 T& emplace(std::initializer_list<U> il, Args&&... args) {
669 this->_emplace_construct_anew(il, BSONCXX_PRIVATE_FWD(args)...);
670 return this->_storage.value;
674 BSONCXX_PRIVATE_CONSTEXPR_CXX14
void swap(optional_common_base& other)
noexcept(
675 std::is_nothrow_move_constructible<T>::value && bsoncxx::detail::is_nothrow_swappable<T>::value) {
676 if (other._has_value) {
677 if (this->_has_value) {
680 swap(this->_storage.value, other._storage.value);
683 this->emplace(std::move(other._storage.value));
686 }
else if (this->_has_value) {
687 other.emplace(std::move(this->_storage.value));
696 storage_type _storage;
697 bool _has_value =
false;
701 template <
typename... Args>
702 void _emplace_construct_anew(Args&&... args)
noexcept(std::is_nothrow_constructible<T, Args&&...>::value) {
703 new (std::addressof(this->_storage.value)) T(BSONCXX_PRIVATE_FWD(args)...);
704 this->_has_value =
true;
708 template <
typename U>
709 void _assign(U&& other_storage) {
710 if (other_storage._has_value) {
712 if (this->_has_value) {
714 this->_storage.value = BSONCXX_PRIVATE_FWD(other_storage)._storage.value;
717 this->_emplace_construct_anew(BSONCXX_PRIVATE_FWD(other_storage)._storage.value);
727struct optional_base_class {
728 using type = optional_assign_base<T>;
733 bool CanHash = std::is_default_constructible<std::hash<bsoncxx::detail::remove_const_t<T>>>::value>
739struct optional_hash<T, false> {
740 optional_hash() =
delete;
741 optional_hash(optional_hash
const&) =
delete;
745struct optional_hash<T, true> {
746 using Td = bsoncxx::detail::remove_const_t<T>;
747 constexpr std::size_t operator()(optional<T>
const& opt)
const
748 noexcept(
noexcept(std::hash<Td>()(std::declval<Td const&>()))) {
749 return opt.has_value() ? std::hash<Td>()(*opt) : std::hash<void*>()(
nullptr);
764struct hash<bsoncxx::v1::stdx::optional<T>> : bsoncxx::v1::stdx::detail::optional_hash<T> {};
769#error "Cannot find a valid polyfill for optional"
786#if defined(BSONCXX_PRIVATE_DOXYGEN_PREPROCESSOR)
Provides macros describing the bsoncxx library configuration.
The bsoncxx v1 macro guard postlude header.
The bsoncxx v1 macro guard prelude header.
A polyfill for std::optional<T>.
Definition optional.hpp:800
Declares C++17 standard library polyfills.
Declares entities whose ABI stability is guaranteed for documented symbols.
type
An enumeration of each BSON type.
Definition types.hpp:43
The top-level namespace within which all bsoncxx library entities are declared.