19#if defined(BSONCXX_POLY_USE_MNMLSTC)
21#include <core/optional.hpp>
27using ::core::in_place;
28using ::core::in_place_t;
29using ::core::make_optional;
31using ::core::nullopt_t;
32using ::core::optional;
38#elif defined(BSONCXX_POLY_USE_BOOST)
40#include <boost/none.hpp>
41#include <boost/optional/optional.hpp>
42#include <boost/optional/optional_io.hpp>
48#if BOOST_VERSION >= 106300
49using in_place_t = ::boost::in_place_init_t;
50const in_place_t in_place{::boost::in_place_init};
53using ::boost::optional;
54using nullopt_t = ::boost::none_t;
56const nullopt_t nullopt{::boost::none};
57using ::boost::make_optional;
63#elif defined(BSONCXX_POLY_USE_STD)
72using ::std::in_place_t;
73using ::std::make_optional;
75using ::std::nullopt_t;
82#elif defined(BSONCXX_POLY_USE_IMPLS)
87#include <initializer_list>
106BSONCXX_PUSH_WARNINGS();
107BSONCXX_DISABLE_WARNING(Clang(
"-Wweak-vtables"));
110class bad_optional_access :
public std::exception {
112 const char* what() const noexcept
override {
113 return "bad_optional_access()";
116BSONCXX_POP_WARNINGS();
120 explicit constexpr nullopt_t(std::nullptr_t)
noexcept {}
124static constexpr nullopt_t nullopt{
nullptr};
127static constexpr struct in_place_t {
133[[noreturn]]
inline void terminate_disengaged_optional(
const char* what)
noexcept {
134 (void)std::fprintf(stderr,
"%s: Invalid attempted use of disengaged optional<T>\n", what);
139[[noreturn]]
inline void throw_bad_optional() {
140 throw bad_optional_access();
145struct optional_base_class;
149std::true_type not_an_optional_f(
const T&);
153std::false_type not_an_optional_f(
const optional<T>&);
157struct not_an_optional : decltype(not_an_optional_f(std::declval<T const&>())) {};
159template <
typename T,
typename Ucvr,
typename U>
160struct enable_opt_conversion
161 : bsoncxx::detail::conjunction<
162 std::is_constructible<T, Ucvr>,
163 bsoncxx::detail::disjunction<
164 std::is_same<T, bool>,
165 bsoncxx::detail::negation<
166 bsoncxx::detail::conjunction<std::is_constructible<T, optional<U>&>,
167 std::is_constructible<T, optional<U> const&>,
168 std::is_constructible<T, optional<U>&&>,
169 std::is_constructible<T, optional<U> const&&>,
170 std::is_convertible<optional<U>&, T>,
171 std::is_convertible<optional<U> const&, T>,
172 std::is_convertible<optional<U>&&, T>,
173 std::is_convertible<optional<U> const&&, T>>>>> {};
175template <
typename From,
typename To>
176struct enable_opt_value_conversion
177 : bsoncxx::detail::conjunction<
178 std::is_constructible<To, From&&>,
179 bsoncxx::detail::negation<bsoncxx::detail::is_alike<From, in_place_t>>,
180 bsoncxx::detail::negation<bsoncxx::detail::is_alike<From, optional<To>>>,
181 bsoncxx::detail::disjunction<
182 bsoncxx::detail::negation<bsoncxx::detail::is_alike<To, bool>>,
183 detail::not_an_optional<bsoncxx::detail::remove_cvref_t<From>>>> {};
188class optional : bsoncxx::detail::equality_operators,
189 bsoncxx::detail::ordering_operators,
190 public detail::optional_base_class<T>
::type {
192 using value_type = T;
193 using reference = bsoncxx::detail::add_lvalue_reference_t<T>;
194 using const_reference =
195 bsoncxx::detail::add_lvalue_reference_t<bsoncxx::detail::add_const_t<T>>;
196 using rvalue_reference = bsoncxx::detail::add_rvalue_reference_t<T>;
197 using const_rvalue_reference =
198 bsoncxx::detail::add_rvalue_reference_t<bsoncxx::detail::add_const_t<T>>;
199 using pointer = bsoncxx::detail::add_pointer_t<T>;
200 using const_pointer = bsoncxx::detail::add_pointer_t<const T>;
204 optional() =
default;
205 constexpr optional(nullopt_t)
noexcept {}
209 optional(
const optional&) =
default;
210 optional(optional&&) =
default;
214 optional& operator=(
const optional&) =
default;
215 optional& operator=(optional&&) =
default;
216 ~optional() =
default;
220 template <
typename... Args>
221 bsoncxx_cxx14_constexpr
explicit optional(in_place_t, Args&&... args)
noexcept(
222 noexcept(T(BSONCXX_FWD(args)...))) {
223 this->emplace(BSONCXX_FWD(args)...);
226 template <
typename U,
typename... Args>
227 bsoncxx_cxx14_constexpr
explicit optional(
229 std::initializer_list<U> il,
230 Args&&... args)
noexcept(
noexcept(T(il, BSONCXX_FWD(args)...))) {
231 this->emplace(il, BSONCXX_FWD(args)...);
238 bsoncxx::detail::requires_t<int,
239 detail::enable_opt_value_conversion<U&&, T>,
240 bsoncxx::detail::negation<std::is_convertible<U&&, T>>> = 0>
241 bsoncxx_cxx14_constexpr
explicit optional(U&& arg)
noexcept(
242 std::is_nothrow_constructible<T, U&&>::value)
243 : optional(in_place, BSONCXX_FWD(arg)) {}
247 template <
typename U = T,
248 bsoncxx::detail::requires_t<int,
249 detail::enable_opt_value_conversion<U&&, T>,
250 std::is_convertible<U&&, T>> = 0>
251 bsoncxx_cxx14_constexpr optional(U&& arg)
noexcept(std::is_nothrow_constructible<T, U&&>::value)
252 : optional(in_place, BSONCXX_FWD(arg)) {}
254 template <
typename U,
255 bsoncxx::detail::requires_t<
257 detail::enable_opt_conversion<T, const U&, U>,
258 bsoncxx::detail::negation<std::is_convertible<U const&, T>>> = 0>
259 bsoncxx_cxx14_constexpr
explicit optional(optional<U>
const& other)
noexcept(
260 std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<const U>>::value) {
261 if (other.has_value()) {
262 this->emplace(*other);
266 template <
typename U,
267 bsoncxx::detail::requires_t<int,
268 detail::enable_opt_conversion<T, const U&, U>,
269 std::is_convertible<U const&, T>> = 0>
270 bsoncxx_cxx14_constexpr optional(optional<U>
const& other)
noexcept(
271 std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<const U>>::value) {
272 if (other.has_value()) {
273 this->emplace(*other);
279 bsoncxx::detail::requires_t<int,
280 detail::enable_opt_conversion<T, U&&, U>,
281 bsoncxx::detail::negation<std::is_convertible<U&&, T>>> = 0>
282 bsoncxx_cxx14_constexpr
explicit optional(optional<U>&& other)
noexcept(
283 std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<U&&>>::value) {
284 if (other.has_value()) {
285 this->emplace(*BSONCXX_FWD(other));
289 template <
typename U,
290 bsoncxx::detail::requires_t<int,
291 detail::enable_opt_conversion<T, U&&, U>,
292 std::is_convertible<U&&, T>> = 0>
293 bsoncxx_cxx14_constexpr optional(optional<U>&& other)
noexcept(
294 std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<U&&>>::value) {
295 if (other.has_value()) {
296 this->emplace(*BSONCXX_FWD(other));
300 constexpr bool has_value() const noexcept {
301 return this->_has_value;
303 constexpr explicit operator bool() const noexcept {
304 return this->has_value();
309 bsoncxx_cxx14_constexpr reference operator*() &
noexcept {
310 _assert_has_value(
"operator*() &");
311 return this->_storage.value;
313 bsoncxx_cxx14_constexpr const_reference operator*() const& noexcept {
314 _assert_has_value(
"operator*() const&");
315 return this->_storage.value;
317 bsoncxx_cxx14_constexpr rvalue_reference operator*() &&
noexcept {
318 _assert_has_value(
"operator*() &&");
319 return static_cast<rvalue_reference
>(**this);
321 bsoncxx_cxx14_constexpr const_rvalue_reference operator*() const&& noexcept {
322 _assert_has_value(
"operator*() const&&");
323 return static_cast<const_rvalue_reference
>(**this);
328 bsoncxx_cxx14_constexpr pointer operator->() noexcept {
329 _assert_has_value(
"operator->()");
330 return std::addressof(**
this);
332 bsoncxx_cxx14_constexpr const_pointer operator->() const noexcept {
333 _assert_has_value(
"operator->() const");
334 return std::addressof(**
this);
339 bsoncxx_cxx14_constexpr reference
value() & {
343 bsoncxx_cxx14_constexpr const_reference
value() const& {
347 bsoncxx_cxx14_constexpr rvalue_reference
value() && {
349 return static_cast<rvalue_reference
>(**this);
351 bsoncxx_cxx14_constexpr const_rvalue_reference
value() const&& {
353 return static_cast<const_rvalue_reference
>(**this);
358 template <
typename U>
359 bsoncxx_cxx14_constexpr value_type value_or(U&& dflt)
const& {
363 return static_cast<value_type
>(BSONCXX_FWD(dflt));
367 template <
typename U>
368 bsoncxx_cxx14_constexpr value_type value_or(U&& dflt) && {
370 return *std::move(*
this);
372 return static_cast<value_type
>(BSONCXX_FWD(dflt));
377 bsoncxx_cxx14_constexpr
void _assert_has_value(
const char* msg)
const noexcept {
378 if (!this->has_value()) {
379 detail::terminate_disengaged_optional(msg);
383 bsoncxx_cxx14_constexpr
void _throw_if_empty()
const {
384 if (!this->has_value()) {
385 detail::throw_bad_optional();
394bsoncxx_cxx14_constexpr optional<bsoncxx::detail::decay_t<T>> make_optional(T&& value)
noexcept(
395 std::is_nothrow_constructible<bsoncxx::detail::decay_t<T>, T&&>::value) {
396 return optional<bsoncxx::detail::decay_t<T>>(BSONCXX_FWD(value));
403template <
typename T,
typename... Args>
404bsoncxx_cxx14_constexpr optional<T> make_optional(Args&&... args)
noexcept(
405 std::is_nothrow_constructible<T, Args&&...>::value) {
406 return optional<T>(in_place, BSONCXX_FWD(args)...);
411template <
typename T,
typename U,
typename... Args>
412bsoncxx_cxx14_constexpr optional<T>
413make_optional(std::initializer_list<U> il, Args&&... args)
noexcept(
414 std::is_nothrow_constructible<T, std::initializer_list<U>, Args&&...>::value) {
415 return optional<T>(in_place, il, BSONCXX_FWD(args)...);
421template <typename T, bool = std::is_trivially_destructible<T>::value>
429 storage_for() noexcept : nothing(0) {}
434 storage_for(
const storage_for&) =
delete;
435 storage_for& operator=(
const storage_for&) =
delete;
439union storage_for<T, true > {
442 storage_for() noexcept : nothing(0) {}
443 storage_for(
const storage_for&) =
delete;
444 storage_for& operator=(
const storage_for&) =
delete;
448enum copymove_classification {
456 bool CanCopy = std::is_copy_constructible<T>::value,
457 bool CanMove = std::is_move_constructible<T>::value>
458constexpr copymove_classification classify_construct() {
459 return CanCopy ? copyable : CanMove ? movable : immobile;
464 bool CanCopy = std::is_copy_assignable<T>::value,
465 bool CanMove = std::is_move_assignable<T>::value>
466constexpr copymove_classification classify_assignment() {
467 return CanCopy ? copyable : CanMove ? movable : immobile;
474class optional_common_base;
477template <typename T, copymove_classification = classify_construct<T>()>
478struct optional_construct_base;
481template <typename T, copymove_classification = classify_assignment<T>()>
482struct optional_assign_base;
484template <
bool TrivialDestruct>
485struct optional_destruct_helper;
488using optional_destruct_base =
489 typename optional_destruct_helper<std::is_trivially_destructible<T>::value>::template base<T>;
492struct optional_assign_base<T, copyable> : optional_construct_base<T> {};
495struct optional_assign_base<T, movable> : optional_construct_base<T> {
498 optional_assign_base() =
default;
499 optional_assign_base(optional_assign_base
const&) =
default;
500 optional_assign_base(optional_assign_base&&) =
default;
501 ~optional_assign_base() =
default;
505 bsoncxx_cxx14_constexpr optional_assign_base& operator=(
const optional_assign_base&) =
delete;
509 bsoncxx_cxx14_constexpr optional_assign_base& operator=(optional_assign_base&& other) =
default;
513struct optional_assign_base<T, immobile> : optional_construct_base<T> {
514 optional_assign_base() =
default;
515 optional_assign_base(optional_assign_base
const&) =
default;
516 optional_assign_base(optional_assign_base&&) =
default;
517 ~optional_assign_base() =
default;
520 optional_assign_base& operator=(
const optional_assign_base&) =
delete;
521 optional_assign_base& operator=(optional_assign_base&&) =
delete;
525struct optional_construct_base<T, copyable> : optional_destruct_base<T> {};
528struct optional_construct_base<T, movable> : optional_destruct_base<T> {
529 optional_construct_base() =
default;
531 optional_construct_base(
const optional_construct_base&) =
delete;
532 optional_construct_base(optional_construct_base&& other) =
default;
533 optional_construct_base& operator=(
const optional_construct_base&) =
default;
534 optional_construct_base& operator=(optional_construct_base&&) =
default;
538struct optional_construct_base<T, immobile> : optional_destruct_base<T> {
539 optional_construct_base() =
default;
540 optional_construct_base(
const optional_construct_base&) =
delete;
541 optional_construct_base& operator=(
const optional_construct_base&) =
default;
542 optional_construct_base& operator=(optional_construct_base&&) =
default;
546struct optional_destruct_helper<false > {
547 template <
typename T>
548 struct base : optional_common_base<T> {
552 base(base
const&) =
default;
553 base(base&&) =
default;
554 base& operator=(
const base&) =
default;
555 base& operator=(base&&) =
default;
565struct optional_destruct_helper<true > {
568 template <
typename T>
569 using base = optional_common_base<T>;
573struct optional_operators_base {
574 template <
typename T,
typename U>
575 friend bsoncxx_cxx14_constexpr
auto tag_invoke(bsoncxx::detail::equal_to,
576 optional<T>
const& left,
577 optional<U>
const& right)
noexcept
578 -> bsoncxx::detail::requires_t<bool, bsoncxx::detail::is_equality_comparable<T, U>> {
579 if (left.has_value() != right.has_value()) {
583 BSONCXX_PUSH_WARNINGS();
584 BSONCXX_DISABLE_WARNING(GNU(
"-Wfloat-equal"));
585 return !left.has_value() || *left == *right;
586 BSONCXX_POP_WARNINGS();
589 template <
typename T,
typename U>
590 friend constexpr auto tag_invoke(bsoncxx::detail::equal_to,
591 optional<T>
const& left,
592 U
const& right)
noexcept -> bsoncxx::detail::
593 requires_t<bool, not_an_optional<U>, bsoncxx::detail::is_equality_comparable<T, U>> {
594 BSONCXX_PUSH_WARNINGS();
595 BSONCXX_DISABLE_WARNING(GNU(
"-Wfloat-equal"));
596 return left.has_value() && *left == right;
597 BSONCXX_POP_WARNINGS();
600 template <
typename T>
601 friend constexpr bool tag_invoke(bsoncxx::detail::equal_to,
602 optional<T>
const& opt,
603 nullopt_t)
noexcept {
604 return !opt.has_value();
607 template <
typename T,
typename U>
608 bsoncxx_cxx14_constexpr
friend auto tag_invoke(bsoncxx::detail::compare_three_way compare,
609 optional<T>
const& left,
610 optional<U>
const& right)
611 -> bsoncxx::detail::requires_t<bsoncxx::detail::strong_ordering,
612 bsoncxx::detail::is_totally_ordered_with<T, U>> {
613 if (left.has_value()) {
614 if (right.has_value()) {
615 return compare(*left, *right);
618 return bsoncxx::detail::strong_ordering::greater;
621 if (right.has_value()) {
623 return bsoncxx::detail::strong_ordering::less;
626 return bsoncxx::detail::strong_ordering::equal;
631 template <
typename T,
typename U>
632 bsoncxx_cxx14_constexpr
friend auto tag_invoke(bsoncxx::detail::compare_three_way compare,
633 optional<T>
const& left,
635 -> bsoncxx::detail::requires_t<bsoncxx::detail::strong_ordering,
637 bsoncxx::detail::is_totally_ordered_with<T, U>> {
638 if (left.has_value()) {
639 return compare(*left, right);
642 return bsoncxx::detail::strong_ordering::less;
645 template <
typename T>
646 constexpr friend bsoncxx::detail::strong_ordering tag_invoke(
647 bsoncxx::detail::compare_three_way compare, optional<T>
const& left, nullopt_t) {
648 return compare(left.has_value(),
false);
653template <typename T, bool IsSwappable = bsoncxx::detail::is_swappable<T>::value>
654struct optional_swap_mixin {};
657struct optional_swap_mixin<T, true> {
658 bsoncxx_cxx14_constexpr
friend void swap(optional<T>& left, optional<T>& right)
noexcept(
659 std::is_nothrow_move_constructible<T>::value&&
660 bsoncxx::detail::is_nothrow_swappable<T>::value) {
667class optional_common_base : optional_operators_base, optional_swap_mixin<T> {
668 using storage_type = detail::storage_for<bsoncxx::detail::remove_const_t<T>>;
671 optional_common_base() =
default;
672 ~optional_common_base() =
default;
674 optional_common_base(
const optional_common_base& other)
noexcept(
675 std::is_nothrow_copy_constructible<T>::value) {
676 if (other._has_value) {
677 this->emplace(other._storage.value);
681 optional_common_base(optional_common_base&& other)
noexcept(
682 std::is_nothrow_move_constructible<T>::value) {
683 if (other._has_value) {
684 this->_emplace_construct_anew(std::move(other)._storage.value);
688 optional_common_base& operator=(
const optional_common_base& other)
noexcept(
689 std::is_nothrow_copy_assignable<T>::value) {
690 this->_assign(BSONCXX_FWD(other));
694 optional_common_base& operator=(optional_common_base&& other)
noexcept(
695 std::is_nothrow_move_assignable<T>::value) {
696 this->_assign(BSONCXX_FWD(other));
701 void reset() noexcept {
702 if (this->_has_value) {
703 this->_storage.value.~T();
705 this->_has_value =
false;
710 template <
typename... Args>
711 T& emplace(Args&&... args) {
713 this->_emplace_construct_anew(BSONCXX_FWD(args)...);
714 return this->_storage.value;
719 template <
typename U,
typename... Args>
720 T& emplace(std::initializer_list<U> il, Args&&... args) {
722 this->_emplace_construct_anew(il, BSONCXX_FWD(args)...);
723 return this->_storage.value;
727 bsoncxx_cxx14_constexpr
void swap(optional_common_base& other)
noexcept(
728 std::is_nothrow_move_constructible<T>::value&&
729 bsoncxx::detail::is_nothrow_swappable<T>::value) {
730 if (other._has_value) {
731 if (this->_has_value) {
734 swap(this->_storage.value, other._storage.value);
737 this->emplace(std::move(other._storage.value));
740 }
else if (this->_has_value) {
741 other.emplace(std::move(this->_storage.value));
750 storage_type _storage;
751 bool _has_value =
false;
755 template <
typename... Args>
756 void _emplace_construct_anew(Args&&... args)
noexcept(
757 std::is_nothrow_constructible<T, Args&&...>::value) {
758 new (std::addressof(this->_storage.value)) T(BSONCXX_FWD(args)...);
759 this->_has_value =
true;
763 template <
typename U>
764 void _assign(U&& other_storage) {
765 if (other_storage._has_value) {
767 if (this->_has_value) {
769 this->_storage.value = BSONCXX_FWD(other_storage)._storage.value;
772 this->_emplace_construct_anew(BSONCXX_FWD(other_storage)._storage.value);
782struct optional_base_class {
783 using type = optional_assign_base<T>;
788 std::is_default_constructible<std::hash<bsoncxx::detail::remove_const_t<T>>>::value>
794struct optional_hash<T, false> {
795 optional_hash() =
delete;
796 optional_hash(
const optional_hash&) =
delete;
800struct optional_hash<T, true> {
801 using Td = bsoncxx::detail::remove_const_t<T>;
802 constexpr std::size_t operator()(
const optional<T>& opt)
const
803 noexcept(
noexcept(std::hash<Td>()(std::declval<Td const&>()))) {
804 return opt.has_value() ? std::hash<Td>()(*opt)
805 : std::hash<void*>()(
nullptr);
820struct hash<
bsoncxx::v_noabi::stdx::optional<T>>
821 : bsoncxx::v_noabi::stdx::detail::optional_hash<T> {};
826#error "Cannot find a valid polyfill for optional"
835#if !defined(BOOST_VERSION) || BOOST_VERSION >= 106300
836using ::bsoncxx::v_noabi::stdx::in_place;
837using ::bsoncxx::v_noabi::stdx::in_place_t;
840using ::bsoncxx::v_noabi::stdx::make_optional;
841using ::bsoncxx::v_noabi::stdx::nullopt;
842using ::bsoncxx::v_noabi::stdx::nullopt_t;
843using ::bsoncxx::v_noabi::stdx::optional;
860#if defined(BSONCXX_PRIVATE_DOXYGEN_PREPROCESSOR)
The bsoncxx macro guard postlude header.
The bsoncxx macro guard prelude header.
A polyfill for std::optional<T>.
Definition optional.hpp:874
BSONCXX_DEPRECATED typedef types::bson_value::view value
Equivalent to bsoncxx::v_noabi::types::bson_value::view.
Definition value.hpp:30
type
An enumeration of each BSON type.
Definition types.hpp:43
The top-level namespace within which all bsoncxx library entities are declared.
The top-level namespace reserved for the C++ standard library.
Provides comparison-related utilities for internal use.
Provides <type_traits>-related polyfills for internal use.