21#if defined(BSONCXX_POLY_USE_STD)
31using std::make_optional;
40#elif defined(BSONCXX_POLY_USE_IMPLS)
50#include <initializer_list>
64BSONCXX_PRIVATE_WARNINGS_PUSH();
65BSONCXX_PRIVATE_WARNINGS_DISABLE(Clang(
"-Wweak-vtables"));
68class bad_optional_access :
public std::exception {
70 char const* what() const noexcept
override {
71 return "bad_optional_access()";
74BSONCXX_PRIVATE_WARNINGS_POP();
78 explicit constexpr nullopt_t(std::nullptr_t)
noexcept {}
82static constexpr nullopt_t nullopt{
nullptr};
85static constexpr struct in_place_t {
91[[noreturn]]
inline void terminate_disengaged_optional(
char const* what)
noexcept {
92 (void)std::fprintf(stderr,
"%s: Invalid attempted use of disengaged optional<T>\n", what);
97[[noreturn]]
inline void throw_bad_optional() {
98 throw bad_optional_access();
103struct optional_base_class;
107std::true_type not_an_optional_f(T
const&);
111std::false_type not_an_optional_f(optional<T>
const&);
115struct not_an_optional : decltype(not_an_optional_f(std::declval<T const&>())){};
117template <
typename T,
typename Ucvr,
typename U>
118struct enable_opt_conversion : bsoncxx::detail::conjunction<
119 std::is_constructible<T, Ucvr>,
120 bsoncxx::detail::disjunction<
121 std::is_same<T, bool>,
122 bsoncxx::detail::negation<bsoncxx::detail::conjunction<
123 std::is_constructible<T, optional<U>&>,
124 std::is_constructible<T, optional<U> const&>,
125 std::is_constructible<T, optional<U>&&>,
126 std::is_constructible<T, optional<U> const&&>,
127 std::is_convertible<optional<U>&, T>,
128 std::is_convertible<optional<U> const&, T>,
129 std::is_convertible<optional<U>&&, T>,
130 std::is_convertible<optional<U> const&&, T>>>>> {};
132template <
typename From,
typename To>
133struct enable_opt_value_conversion : bsoncxx::detail::conjunction<
134 std::is_constructible<To, From&&>,
135 bsoncxx::detail::negation<bsoncxx::detail::is_alike<From, in_place_t>>,
136 bsoncxx::detail::negation<bsoncxx::detail::is_alike<From, optional<To>>>,
137 bsoncxx::detail::disjunction<
138 bsoncxx::detail::negation<bsoncxx::detail::is_alike<To, bool>>,
139 detail::not_an_optional<bsoncxx::detail::remove_cvref_t<From>>>> {};
144class optional : bsoncxx::detail::equality_operators,
145 bsoncxx::detail::ordering_operators,
146 public detail::optional_base_class<T>
::type {
148 using value_type = T;
149 using reference = bsoncxx::detail::add_lvalue_reference_t<T>;
150 using const_reference = bsoncxx::detail::add_lvalue_reference_t<bsoncxx::detail::add_const_t<T>>;
151 using rvalue_reference = bsoncxx::detail::add_rvalue_reference_t<T>;
152 using const_rvalue_reference = bsoncxx::detail::add_rvalue_reference_t<bsoncxx::detail::add_const_t<T>>;
153 using pointer = bsoncxx::detail::add_pointer_t<T>;
154 using const_pointer = bsoncxx::detail::add_pointer_t<T const>;
158 optional() =
default;
159 constexpr optional(nullopt_t)
noexcept {}
163 optional(optional
const&) =
default;
164 optional(optional&&) =
default;
168 optional& operator=(optional
const&) =
default;
169 optional& operator=(optional&&) =
default;
170 ~optional() =
default;
174 template <
typename... Args>
175 BSONCXX_PRIVATE_CONSTEXPR_CXX14
explicit optional(in_place_t, Args&&... args)
noexcept(
176 noexcept(T(BSONCXX_PRIVATE_FWD(args)...))) {
177 this->emplace(BSONCXX_PRIVATE_FWD(args)...);
180 template <
typename U,
typename... Args>
181 BSONCXX_PRIVATE_CONSTEXPR_CXX14
explicit optional(in_place_t, std::initializer_list<U> il, Args&&... args)
noexcept(
182 noexcept(T(il, BSONCXX_PRIVATE_FWD(args)...))) {
183 this->emplace(il, BSONCXX_PRIVATE_FWD(args)...);
190 bsoncxx::detail::requires_t<
192 detail::enable_opt_value_conversion<U&&, T>,
193 bsoncxx::detail::negation<std::is_convertible<U&&, T>>> = 0>
194 BSONCXX_PRIVATE_CONSTEXPR_CXX14
explicit optional(U&& arg)
noexcept(std::is_nothrow_constructible<T, U&&>::value)
195 : optional(in_place, BSONCXX_PRIVATE_FWD(arg)) {}
201 bsoncxx::detail::requires_t<int, detail::enable_opt_value_conversion<U&&, T>, std::is_convertible<U&&, T>> = 0>
202 BSONCXX_PRIVATE_CONSTEXPR_CXX14 optional(U&& arg)
noexcept(std::is_nothrow_constructible<T, U&&>::value)
203 : optional(in_place, BSONCXX_PRIVATE_FWD(arg)) {}
207 bsoncxx::detail::requires_t<
209 detail::enable_opt_conversion<T, U const&, U>,
210 bsoncxx::detail::negation<std::is_convertible<U const&, T>>> = 0>
211 BSONCXX_PRIVATE_CONSTEXPR_CXX14
explicit optional(optional<U>
const& other)
noexcept(
212 std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<U const>>::value) {
213 if (other.has_value()) {
214 this->emplace(*other);
220 bsoncxx::detail::requires_t<
222 detail::enable_opt_conversion<T, U const&, U>,
223 std::is_convertible<U const&, T>> = 0>
224 BSONCXX_PRIVATE_CONSTEXPR_CXX14 optional(optional<U>
const& other)
noexcept(
225 std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<U const>>::value) {
226 if (other.has_value()) {
227 this->emplace(*other);
233 bsoncxx::detail::requires_t<
235 detail::enable_opt_conversion<T, U&&, U>,
236 bsoncxx::detail::negation<std::is_convertible<U&&, T>>> = 0>
237 BSONCXX_PRIVATE_CONSTEXPR_CXX14
explicit optional(optional<U>&& other)
noexcept(
238 std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<U&&>>::value) {
239 if (other.has_value()) {
240 this->emplace(*BSONCXX_PRIVATE_FWD(other));
246 bsoncxx::detail::requires_t<int, detail::enable_opt_conversion<T, U&&, U>, std::is_convertible<U&&, T>> = 0>
247 BSONCXX_PRIVATE_CONSTEXPR_CXX14 optional(optional<U>&& other)
noexcept(
248 std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<U&&>>::value) {
249 if (other.has_value()) {
250 this->emplace(*BSONCXX_PRIVATE_FWD(other));
254 constexpr bool has_value() const noexcept {
255 return this->_has_value;
257 constexpr explicit operator bool() const noexcept {
258 return this->has_value();
263 BSONCXX_PRIVATE_CONSTEXPR_CXX14 reference operator*() &
noexcept {
264 _assert_has_value(
"operator*() &");
265 return this->_storage.value;
267 BSONCXX_PRIVATE_CONSTEXPR_CXX14 const_reference operator*() const& noexcept {
268 _assert_has_value(
"operator*() const&");
269 return this->_storage.value;
271 BSONCXX_PRIVATE_CONSTEXPR_CXX14 rvalue_reference operator*() &&
noexcept {
272 _assert_has_value(
"operator*() &&");
273 return static_cast<rvalue_reference
>(**this);
275 BSONCXX_PRIVATE_CONSTEXPR_CXX14 const_rvalue_reference operator*() const&& noexcept {
276 _assert_has_value(
"operator*() const&&");
277 return static_cast<const_rvalue_reference
>(**this);
282 BSONCXX_PRIVATE_CONSTEXPR_CXX14 pointer operator->() noexcept {
283 _assert_has_value(
"operator->()");
284 return std::addressof(**
this);
286 BSONCXX_PRIVATE_CONSTEXPR_CXX14 const_pointer operator->() const noexcept {
287 _assert_has_value(
"operator->() const");
288 return std::addressof(**
this);
293 BSONCXX_PRIVATE_CONSTEXPR_CXX14 reference
value() & {
297 BSONCXX_PRIVATE_CONSTEXPR_CXX14 const_reference
value() const& {
301 BSONCXX_PRIVATE_CONSTEXPR_CXX14 rvalue_reference
value() && {
303 return static_cast<rvalue_reference
>(**this);
305 BSONCXX_PRIVATE_CONSTEXPR_CXX14 const_rvalue_reference
value() const&& {
307 return static_cast<const_rvalue_reference
>(**this);
312 template <
typename U>
313 BSONCXX_PRIVATE_CONSTEXPR_CXX14 value_type value_or(U&& dflt)
const& {
317 return static_cast<value_type
>(BSONCXX_PRIVATE_FWD(dflt));
321 template <
typename U>
322 BSONCXX_PRIVATE_CONSTEXPR_CXX14 value_type value_or(U&& dflt) && {
324 return *std::move(*
this);
326 return static_cast<value_type
>(BSONCXX_PRIVATE_FWD(dflt));
331 BSONCXX_PRIVATE_CONSTEXPR_CXX14
void _assert_has_value(
char const* msg)
const noexcept {
332 if (!this->has_value()) {
333 detail::terminate_disengaged_optional(msg);
337 BSONCXX_PRIVATE_CONSTEXPR_CXX14
void _throw_if_empty()
const {
338 if (!this->has_value()) {
339 detail::throw_bad_optional();
349 std::is_nothrow_constructible<bsoncxx::detail::decay_t<T>, T&&>::value) {
357template <
typename T,
typename... Args>
358BSONCXX_PRIVATE_CONSTEXPR_CXX14
optional<T> make_optional(Args&&... args)
noexcept(
359 std::is_nothrow_constructible<T, Args&&...>::value) {
360 return optional<T>(in_place, BSONCXX_PRIVATE_FWD(args)...);
365template <
typename T,
typename U,
typename... Args>
366BSONCXX_PRIVATE_CONSTEXPR_CXX14
optional<T> make_optional(std::initializer_list<U> il, Args&&... args)
noexcept(
367 std::is_nothrow_constructible<T, std::initializer_list<U>, Args&&...>::value) {
368 return optional<T>(in_place, il, BSONCXX_PRIVATE_FWD(args)...);
374template <typename T, bool = std::is_trivially_destructible<T>::value>
382 storage_for() noexcept : nothing(0) {}
387 storage_for(storage_for
const&) =
delete;
388 storage_for& operator=(storage_for
const&) =
delete;
392union storage_for<T, true > {
395 storage_for() noexcept : nothing(0) {}
396 storage_for(storage_for
const&) =
delete;
397 storage_for& operator=(storage_for
const&) =
delete;
401enum copymove_classification {
410 bool CanCopy = std::is_copy_constructible<T>::value,
411 bool CanMove = std::is_move_constructible<T>::value>
412constexpr copymove_classification classify_construct() {
413 return CanCopy ? copyable : CanMove ? movable : immobile;
419 bool CanCopy = std::is_copy_assignable<T>::value,
420 bool CanMove = std::is_move_assignable<T>::value>
421constexpr copymove_classification classify_assignment() {
422 return CanCopy ? copyable : CanMove ? movable : immobile;
429class optional_common_base;
432template <typename T, copymove_classification = classify_construct<T>()>
433struct optional_construct_base;
436template <typename T, copymove_classification = classify_assignment<T>()>
437struct optional_assign_base;
439template <
bool TrivialDestruct>
440struct optional_destruct_helper;
443using optional_destruct_base =
444 typename optional_destruct_helper<std::is_trivially_destructible<T>::value>::template base<T>;
447struct optional_assign_base<T, copyable> : optional_construct_base<T> {};
450struct optional_assign_base<T, movable> : optional_construct_base<T> {
453 optional_assign_base() =
default;
454 optional_assign_base(optional_assign_base
const&) =
default;
455 optional_assign_base(optional_assign_base&&) =
default;
456 ~optional_assign_base() =
default;
460 BSONCXX_PRIVATE_CONSTEXPR_CXX14 optional_assign_base& operator=(optional_assign_base
const&) =
delete;
464 BSONCXX_PRIVATE_CONSTEXPR_CXX14 optional_assign_base& operator=(optional_assign_base&&) =
default;
468struct optional_assign_base<T, immobile> : optional_construct_base<T> {
469 optional_assign_base() =
default;
470 optional_assign_base(optional_assign_base
const&) =
default;
471 optional_assign_base(optional_assign_base&&) =
default;
472 ~optional_assign_base() =
default;
475 optional_assign_base& operator=(optional_assign_base
const&) =
delete;
476 optional_assign_base& operator=(optional_assign_base&&) =
delete;
480struct optional_construct_base<T, copyable> : optional_destruct_base<T> {};
483struct optional_construct_base<T, movable> : optional_destruct_base<T> {
484 optional_construct_base() =
default;
486 optional_construct_base(optional_construct_base
const&) =
delete;
487 optional_construct_base(optional_construct_base&&) =
default;
488 optional_construct_base& operator=(optional_construct_base
const&) =
default;
489 optional_construct_base& operator=(optional_construct_base&&) =
default;
493struct optional_construct_base<T, immobile> : optional_destruct_base<T> {
494 optional_construct_base() =
default;
495 optional_construct_base(optional_construct_base
const&) =
delete;
496 optional_construct_base& operator=(optional_construct_base
const&) =
default;
497 optional_construct_base& operator=(optional_construct_base&&) =
default;
501struct optional_destruct_helper<false > {
502 template <
typename T>
503 struct base : optional_common_base<T> {
507 base(base
const&) =
default;
508 base(base&&) =
default;
509 base& operator=(base
const&) =
default;
510 base& operator=(base&&) =
default;
520struct optional_destruct_helper<true > {
523 template <
typename T>
524 using base = optional_common_base<T>;
528struct optional_operators_base {
529 template <
typename T,
typename U>
530 friend BSONCXX_PRIVATE_CONSTEXPR_CXX14
auto
531 tag_invoke(bsoncxx::detail::equal_to, optional<T>
const& left, optional<U>
const& right)
noexcept
532 -> bsoncxx::detail::requires_t<bool, bsoncxx::detail::is_equality_comparable<T, U>> {
533 if (left.has_value() != right.has_value()) {
537 BSONCXX_PRIVATE_WARNINGS_PUSH();
538 BSONCXX_PRIVATE_WARNINGS_DISABLE(GNU(
"-Wfloat-equal"));
539 return !left.has_value() || *left == *right;
540 BSONCXX_PRIVATE_WARNINGS_POP();
543 template <
typename T,
typename U>
544 friend constexpr auto tag_invoke(bsoncxx::detail::equal_to, optional<T>
const& left, U
const& right)
noexcept
545 -> bsoncxx::detail::requires_t<bool, not_an_optional<U>, bsoncxx::detail::is_equality_comparable<T, U>> {
546 BSONCXX_PRIVATE_WARNINGS_PUSH();
547 BSONCXX_PRIVATE_WARNINGS_DISABLE(GNU(
"-Wfloat-equal"));
548 return left.has_value() && *left == right;
549 BSONCXX_PRIVATE_WARNINGS_POP();
552 template <
typename T>
553 friend constexpr bool tag_invoke(bsoncxx::detail::equal_to, optional<T>
const& opt, nullopt_t)
noexcept {
554 return !opt.has_value();
557 template <
typename T,
typename U>
558 BSONCXX_PRIVATE_CONSTEXPR_CXX14
friend auto
559 tag_invoke(bsoncxx::detail::compare_three_way compare, optional<T>
const& left, optional<U>
const& right)
560 -> bsoncxx::detail::requires_t<
561 bsoncxx::detail::strong_ordering,
562 bsoncxx::detail::is_totally_ordered_with<T, U>> {
563 if (left.has_value()) {
564 if (right.has_value()) {
565 return compare(*left, *right);
568 return bsoncxx::detail::strong_ordering::greater;
571 if (right.has_value()) {
573 return bsoncxx::detail::strong_ordering::less;
576 return bsoncxx::detail::strong_ordering::equal;
581 template <
typename T,
typename U>
582 BSONCXX_PRIVATE_CONSTEXPR_CXX14
friend auto
583 tag_invoke(bsoncxx::detail::compare_three_way compare, optional<T>
const& left, U
const& right)
584 -> bsoncxx::detail::requires_t<
585 bsoncxx::detail::strong_ordering,
587 bsoncxx::detail::is_totally_ordered_with<T, U>> {
588 if (left.has_value()) {
589 return compare(*left, right);
592 return bsoncxx::detail::strong_ordering::less;
595 template <
typename T>
596 constexpr friend bsoncxx::detail::strong_ordering
597 tag_invoke(bsoncxx::detail::compare_three_way compare, optional<T>
const& left, nullopt_t) {
598 return compare(left.has_value(),
false);
603template <typename T, bool IsSwappable = bsoncxx::detail::is_swappable<T>::value>
604struct optional_swap_mixin {};
607struct optional_swap_mixin<T, true> {
608 BSONCXX_PRIVATE_CONSTEXPR_CXX14
friend void swap(optional<T>& left, optional<T>& right)
noexcept(
609 std::is_nothrow_move_constructible<T>::value && bsoncxx::detail::is_nothrow_swappable<T>::value) {
616class optional_common_base : optional_operators_base, optional_swap_mixin<T> {
617 using storage_type = detail::storage_for<bsoncxx::detail::remove_const_t<T>>;
620 optional_common_base() =
default;
621 ~optional_common_base() =
default;
623 optional_common_base(optional_common_base
const& other)
noexcept(std::is_nothrow_copy_constructible<T>::value) {
624 if (other._has_value) {
625 this->emplace(other._storage.value);
629 optional_common_base(optional_common_base&& other)
noexcept(std::is_nothrow_move_constructible<T>::value) {
630 if (other._has_value) {
631 this->_emplace_construct_anew(std::move(other)._storage.value);
635 optional_common_base& operator=(optional_common_base
const& other)
noexcept(
636 std::is_nothrow_copy_assignable<T>::value) {
637 this->_assign(BSONCXX_PRIVATE_FWD(other));
641 optional_common_base& operator=(optional_common_base&& other)
noexcept(std::is_nothrow_move_assignable<T>::value) {
642 this->_assign(BSONCXX_PRIVATE_FWD(other));
647 void reset() noexcept {
648 if (this->_has_value) {
649 this->_storage.value.~T();
651 this->_has_value =
false;
656 template <
typename... Args>
657 T& emplace(Args&&... args) {
659 this->_emplace_construct_anew(BSONCXX_PRIVATE_FWD(args)...);
660 return this->_storage.value;
665 template <
typename U,
typename... Args>
666 T& emplace(std::initializer_list<U> il, Args&&... args) {
668 this->_emplace_construct_anew(il, BSONCXX_PRIVATE_FWD(args)...);
669 return this->_storage.value;
673 BSONCXX_PRIVATE_CONSTEXPR_CXX14
void swap(optional_common_base& other)
noexcept(
674 std::is_nothrow_move_constructible<T>::value && bsoncxx::detail::is_nothrow_swappable<T>::value) {
675 if (other._has_value) {
676 if (this->_has_value) {
679 swap(this->_storage.value, other._storage.value);
682 this->emplace(std::move(other._storage.value));
685 }
else if (this->_has_value) {
686 other.emplace(std::move(this->_storage.value));
695 storage_type _storage;
696 bool _has_value =
false;
700 template <
typename... Args>
701 void _emplace_construct_anew(Args&&... args)
noexcept(std::is_nothrow_constructible<T, Args&&...>::value) {
702 new (std::addressof(this->_storage.value)) T(BSONCXX_PRIVATE_FWD(args)...);
703 this->_has_value =
true;
707 template <
typename U>
708 void _assign(U&& other_storage) {
709 if (other_storage._has_value) {
711 if (this->_has_value) {
713 this->_storage.value = BSONCXX_PRIVATE_FWD(other_storage)._storage.value;
716 this->_emplace_construct_anew(BSONCXX_PRIVATE_FWD(other_storage)._storage.value);
726struct optional_base_class {
727 using type = optional_assign_base<T>;
732 bool CanHash = std::is_default_constructible<std::hash<bsoncxx::detail::remove_const_t<T>>>::value>
738struct optional_hash<T, false> {
739 optional_hash() =
delete;
740 optional_hash(optional_hash
const&) =
delete;
744struct optional_hash<T, true> {
745 using Td = bsoncxx::detail::remove_const_t<T>;
746 constexpr std::size_t operator()(optional<T>
const& opt)
const
747 noexcept(
noexcept(std::hash<Td>()(std::declval<Td const&>()))) {
748 return opt.has_value() ? std::hash<Td>()(*opt) : std::hash<void*>()(
nullptr);
763struct hash<
bsoncxx::v1::stdx::optional<T>> : bsoncxx::v1::stdx::detail::optional_hash<T> {};
768#error "Cannot find a valid polyfill for optional"
785#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:799
Declares C++17 standard library polyfills.
Declares entities whose ABI stability is guaranteed for documented symbols.
@ bsoncxx
From the bsoncxx library.
Definition exception.hpp:39
bson_value::value value
Equivalent to bsoncxx::v_noabi::types::bson_value::value.
Definition value-fwd.hpp:35
type
An enumeration of each BSON type.
Definition types.hpp:47
The top-level namespace within which all bsoncxx library entities are declared.