19#if defined(BSONCXX_POLY_USE_STD) 
   28using ::std::in_place_t;
 
   29using ::std::make_optional;
 
   31using ::std::nullopt_t;
 
   38#elif defined(BSONCXX_POLY_USE_IMPLS) 
   43#include <initializer_list> 
   62BSONCXX_PUSH_WARNINGS();
 
   63BSONCXX_DISABLE_WARNING(Clang(
"-Wweak-vtables"));
 
   66class bad_optional_access : 
public std::exception {
 
   68    const char* what() const noexcept
 override {
 
   69        return "bad_optional_access()";
 
   72BSONCXX_POP_WARNINGS();
 
   76    explicit constexpr nullopt_t(std::nullptr_t) 
noexcept {}
 
   80static constexpr nullopt_t nullopt{
nullptr};
 
   83static constexpr struct in_place_t {
 
   89[[noreturn]] 
inline void terminate_disengaged_optional(
const char* what) 
noexcept {
 
   90    (void)std::fprintf(stderr, 
"%s: Invalid attempted use of disengaged optional<T>\n", what);
 
   95[[noreturn]] 
inline void throw_bad_optional() {
 
   96    throw bad_optional_access();
 
  101struct optional_base_class;
 
  105std::true_type not_an_optional_f(
const T&);
 
  109std::false_type not_an_optional_f(
const optional<T>&);
 
  113struct not_an_optional : decltype(not_an_optional_f(std::declval<T const&>())) {};
 
  115template <
typename T, 
typename Ucvr, 
typename U>
 
  116struct enable_opt_conversion
 
  117    : bsoncxx::detail::conjunction<  
 
  118          std::is_constructible<T, Ucvr>,
 
  119          bsoncxx::detail::disjunction<  
 
  120              std::is_same<T, bool>,
 
  121              bsoncxx::detail::negation<
 
  122                  bsoncxx::detail::conjunction<std::is_constructible<T, optional<U>&>,
 
  123                                               std::is_constructible<T, optional<U> const&>,
 
  124                                               std::is_constructible<T, optional<U>&&>,
 
  125                                               std::is_constructible<T, optional<U> const&&>,
 
  126                                               std::is_convertible<optional<U>&, T>,
 
  127                                               std::is_convertible<optional<U> const&, T>,
 
  128                                               std::is_convertible<optional<U>&&, T>,
 
  129                                               std::is_convertible<optional<U> const&&, T>>>>> {};
 
  131template <
typename From, 
typename To>
 
  132struct enable_opt_value_conversion   
 
  133    : 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 =
 
  151        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 =
 
  154        bsoncxx::detail::add_rvalue_reference_t<bsoncxx::detail::add_const_t<T>>;
 
  155    using pointer = bsoncxx::detail::add_pointer_t<T>;
 
  156    using const_pointer = bsoncxx::detail::add_pointer_t<const T>;
 
  160    optional() = 
default;
 
  161    constexpr optional(nullopt_t) 
noexcept {}
 
  165    optional(
const optional&) = 
default;
 
  166    optional(optional&&) = 
default;
 
  170    optional& operator=(
const optional&) = 
default;
 
  171    optional& operator=(optional&&) = 
default;
 
  172    ~optional() = 
default;
 
  176    template <
typename... Args>
 
  177    bsoncxx_cxx14_constexpr 
explicit optional(in_place_t, Args&&... args) 
noexcept(
 
  178        noexcept(T(BSONCXX_FWD(args)...))) {
 
  179        this->emplace(BSONCXX_FWD(args)...);
 
  182    template <
typename U, 
typename... Args>
 
  183    bsoncxx_cxx14_constexpr 
explicit optional(
 
  185        std::initializer_list<U> il,
 
  186        Args&&... args) 
noexcept(
noexcept(T(il, BSONCXX_FWD(args)...))) {
 
  187        this->emplace(il, BSONCXX_FWD(args)...);
 
  194        bsoncxx::detail::requires_t<int,
 
  195                                    detail::enable_opt_value_conversion<U&&, T>,
 
  196                                    bsoncxx::detail::negation<std::is_convertible<U&&, T>>> = 0>
 
  197    bsoncxx_cxx14_constexpr 
explicit optional(U&& arg) 
noexcept(
 
  198        std::is_nothrow_constructible<T, U&&>::value)
 
  199        : optional(in_place, BSONCXX_FWD(arg)) {}
 
  203    template <
typename U = T,
 
  204              bsoncxx::detail::requires_t<int,
 
  205                                          detail::enable_opt_value_conversion<U&&, T>,
 
  206                                          std::is_convertible<U&&, T>> = 0>
 
  207    bsoncxx_cxx14_constexpr optional(U&& arg) 
noexcept(std::is_nothrow_constructible<T, U&&>::value)
 
  208        : optional(in_place, BSONCXX_FWD(arg)) {}
 
  210    template <
typename U,
 
  211              bsoncxx::detail::requires_t<
 
  213                  detail::enable_opt_conversion<T, const U&, U>,
 
  214                  bsoncxx::detail::negation<std::is_convertible<U const&, T>>> = 0>
 
  215    bsoncxx_cxx14_constexpr 
explicit optional(optional<U> 
const& other) 
noexcept(
 
  216        std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<const U>>::value) {
 
  217        if (other.has_value()) {
 
  218            this->emplace(*other);
 
  222    template <
typename U,
 
  223              bsoncxx::detail::requires_t<int,
 
  224                                          detail::enable_opt_conversion<T, const U&, U>,
 
  225                                          std::is_convertible<U const&, T>> = 0>
 
  226    bsoncxx_cxx14_constexpr optional(optional<U> 
const& other) 
noexcept(
 
  227        std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<const U>>::value) {
 
  228        if (other.has_value()) {
 
  229            this->emplace(*other);
 
  235        bsoncxx::detail::requires_t<int,
 
  236                                    detail::enable_opt_conversion<T, U&&, U>,
 
  237                                    bsoncxx::detail::negation<std::is_convertible<U&&, T>>> = 0>
 
  238    bsoncxx_cxx14_constexpr 
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_FWD(other));
 
  245    template <
typename U,
 
  246              bsoncxx::detail::requires_t<int,
 
  247                                          detail::enable_opt_conversion<T, U&&, U>,
 
  248                                          std::is_convertible<U&&, T>> = 0>
 
  249    bsoncxx_cxx14_constexpr optional(optional<U>&& other) 
noexcept(
 
  250        std::is_nothrow_constructible<T, bsoncxx::detail::add_lvalue_reference_t<U&&>>::value) {
 
  251        if (other.has_value()) {
 
  252            this->emplace(*BSONCXX_FWD(other));
 
  256    constexpr bool has_value() const noexcept {
 
  257        return this->_has_value;
 
  259    constexpr explicit operator bool() const noexcept {
 
  260        return this->has_value();
 
  265    bsoncxx_cxx14_constexpr reference operator*() & 
noexcept {
 
  266        _assert_has_value(
"operator*() &");
 
  267        return this->_storage.value;
 
  269    bsoncxx_cxx14_constexpr const_reference operator*() const& noexcept {
 
  270        _assert_has_value(
"operator*() const&");
 
  271        return this->_storage.value;
 
  273    bsoncxx_cxx14_constexpr rvalue_reference operator*() && 
noexcept {
 
  274        _assert_has_value(
"operator*() &&");
 
  275        return static_cast<rvalue_reference
>(**this);
 
  277    bsoncxx_cxx14_constexpr const_rvalue_reference operator*() const&& noexcept {
 
  278        _assert_has_value(
"operator*() const&&");
 
  279        return static_cast<const_rvalue_reference
>(**this);
 
  284    bsoncxx_cxx14_constexpr pointer operator->() noexcept {
 
  285        _assert_has_value(
"operator->()");
 
  286        return std::addressof(**
this);
 
  288    bsoncxx_cxx14_constexpr const_pointer operator->() const noexcept {
 
  289        _assert_has_value(
"operator->() const");
 
  290        return std::addressof(**
this);
 
  295    bsoncxx_cxx14_constexpr reference value() & {
 
  299    bsoncxx_cxx14_constexpr const_reference value() const& {
 
  303    bsoncxx_cxx14_constexpr rvalue_reference value() && {
 
  305        return static_cast<rvalue_reference
>(**this);
 
  307    bsoncxx_cxx14_constexpr const_rvalue_reference value() const&& {
 
  309        return static_cast<const_rvalue_reference
>(**this);
 
  314    template <
typename U>
 
  315    bsoncxx_cxx14_constexpr value_type value_or(U&& dflt) 
const& {
 
  319            return static_cast<value_type
>(BSONCXX_FWD(dflt));
 
  323    template <
typename U>
 
  324    bsoncxx_cxx14_constexpr value_type value_or(U&& dflt) && {
 
  326            return *std::move(*
this);
 
  328            return static_cast<value_type
>(BSONCXX_FWD(dflt));
 
  333    bsoncxx_cxx14_constexpr 
void _assert_has_value(
const char* msg) 
const noexcept {
 
  334        if (!this->has_value()) {
 
  335            detail::terminate_disengaged_optional(msg);
 
  339    bsoncxx_cxx14_constexpr 
void _throw_if_empty()
 const {
 
  340        if (!this->has_value()) {
 
  341            detail::throw_bad_optional();
 
  350bsoncxx_cxx14_constexpr optional<bsoncxx::detail::decay_t<T>> make_optional(T&& value) 
noexcept(
 
  351    std::is_nothrow_constructible<bsoncxx::detail::decay_t<T>, T&&>::value) {
 
  352    return optional<bsoncxx::detail::decay_t<T>>(BSONCXX_FWD(value));
 
  359template <
typename T, 
typename... Args>
 
  360bsoncxx_cxx14_constexpr optional<T> make_optional(Args&&... args) 
noexcept(
 
  361    std::is_nothrow_constructible<T, Args&&...>::value) {
 
  362    return optional<T>(in_place, BSONCXX_FWD(args)...);
 
  367template <
typename T, 
typename U, 
typename... Args>
 
  368bsoncxx_cxx14_constexpr optional<T>
 
  369make_optional(std::initializer_list<U> il, Args&&... args) 
noexcept(
 
  370    std::is_nothrow_constructible<T, std::initializer_list<U>, Args&&...>::value) {
 
  371    return optional<T>(in_place, il, BSONCXX_FWD(args)...);
 
  377template <typename T, bool = std::is_trivially_destructible<T>::value>
 
  385    storage_for() noexcept : nothing(0) {}
 
  390    storage_for(
const storage_for&) = 
delete;
 
  391    storage_for& operator=(
const storage_for&) = 
delete;
 
  395union storage_for<T, true > {
 
  398    storage_for() noexcept : nothing(0) {}
 
  399    storage_for(
const storage_for&) = 
delete;
 
  400    storage_for& operator=(
const storage_for&) = 
delete;
 
  404enum copymove_classification {
 
  412          bool CanCopy = std::is_copy_constructible<T>::value,
 
  413          bool CanMove = std::is_move_constructible<T>::value>
 
  414constexpr copymove_classification classify_construct() {
 
  415    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_cxx14_constexpr optional_assign_base& operator=(
const optional_assign_base&) = 
delete;
 
  465    bsoncxx_cxx14_constexpr 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=(
const optional_assign_base&) = 
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(
const optional_construct_base&) = 
delete;
 
  488    optional_construct_base(optional_construct_base&&) = 
default;
 
  489    optional_construct_base& operator=(
const optional_construct_base&) = 
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(
const optional_construct_base&) = 
delete;
 
  497    optional_construct_base& operator=(
const optional_construct_base&) = 
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=(
const base&) = 
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_cxx14_constexpr 
auto tag_invoke(bsoncxx::detail::equal_to,
 
  532                                                   optional<T> 
const& left,
 
  533                                                   optional<U> 
const& right) 
noexcept 
  534        -> bsoncxx::detail::requires_t<bool, bsoncxx::detail::is_equality_comparable<T, U>> {
 
  535        if (left.has_value() != right.has_value()) {
 
  539        BSONCXX_PUSH_WARNINGS();
 
  540        BSONCXX_DISABLE_WARNING(GNU(
"-Wfloat-equal"));
 
  541        return !left.has_value() || *left == *right;
 
  542        BSONCXX_POP_WARNINGS();
 
  545    template <
typename T, 
typename U>
 
  546    friend constexpr auto tag_invoke(bsoncxx::detail::equal_to,
 
  547                                     optional<T> 
const& left,
 
  548                                     U 
const& right) 
noexcept -> bsoncxx::detail::
 
  549        requires_t<bool, not_an_optional<U>, bsoncxx::detail::is_equality_comparable<T, U>> {
 
  550        BSONCXX_PUSH_WARNINGS();
 
  551        BSONCXX_DISABLE_WARNING(GNU(
"-Wfloat-equal"));
 
  552        return left.has_value() && *left == right;
 
  553        BSONCXX_POP_WARNINGS();
 
  556    template <
typename T>
 
  557    friend constexpr bool tag_invoke(bsoncxx::detail::equal_to,
 
  558                                     optional<T> 
const& opt,
 
  559                                     nullopt_t) 
noexcept {
 
  560        return !opt.has_value();
 
  563    template <
typename T, 
typename U>
 
  564    bsoncxx_cxx14_constexpr 
friend auto tag_invoke(bsoncxx::detail::compare_three_way compare,
 
  565                                                   optional<T> 
const& left,
 
  566                                                   optional<U> 
const& right)
 
  567        -> bsoncxx::detail::requires_t<bsoncxx::detail::strong_ordering,
 
  568                                       bsoncxx::detail::is_totally_ordered_with<T, U>> {
 
  569        if (left.has_value()) {
 
  570            if (right.has_value()) {
 
  571                return compare(*left, *right);
 
  574                return bsoncxx::detail::strong_ordering::greater;
 
  577            if (right.has_value()) {
 
  579                return bsoncxx::detail::strong_ordering::less;
 
  582                return bsoncxx::detail::strong_ordering::equal;
 
  587    template <
typename T, 
typename U>
 
  588    bsoncxx_cxx14_constexpr 
friend auto tag_invoke(bsoncxx::detail::compare_three_way compare,
 
  589                                                   optional<T> 
const& left,
 
  591        -> bsoncxx::detail::requires_t<bsoncxx::detail::strong_ordering,
 
  593                                       bsoncxx::detail::is_totally_ordered_with<T, U>> {
 
  594        if (left.has_value()) {
 
  595            return compare(*left, right);
 
  598        return bsoncxx::detail::strong_ordering::less;
 
  601    template <
typename T>
 
  602    constexpr friend bsoncxx::detail::strong_ordering tag_invoke(
 
  603        bsoncxx::detail::compare_three_way compare, optional<T> 
const& left, nullopt_t) {
 
  604        return compare(left.has_value(), 
false);
 
  609template <typename T, bool IsSwappable = bsoncxx::detail::is_swappable<T>::value>
 
  610struct optional_swap_mixin {};
 
  613struct optional_swap_mixin<T, true> {
 
  614    bsoncxx_cxx14_constexpr 
friend void swap(optional<T>& left, optional<T>& right) 
noexcept(
 
  615        std::is_nothrow_move_constructible<T>::value&&
 
  616            bsoncxx::detail::is_nothrow_swappable<T>::value) {
 
  623class optional_common_base : optional_operators_base, optional_swap_mixin<T> {
 
  624    using storage_type = detail::storage_for<bsoncxx::detail::remove_const_t<T>>;
 
  627    optional_common_base() = 
default;
 
  628    ~optional_common_base() = 
default;
 
  630    optional_common_base(
const optional_common_base& other) 
noexcept(
 
  631        std::is_nothrow_copy_constructible<T>::value) {
 
  632        if (other._has_value) {
 
  633            this->emplace(other._storage.value);
 
  637    optional_common_base(optional_common_base&& other) 
noexcept(
 
  638        std::is_nothrow_move_constructible<T>::value) {
 
  639        if (other._has_value) {
 
  640            this->_emplace_construct_anew(std::move(other)._storage.value);
 
  644    optional_common_base& operator=(
const optional_common_base& other) 
noexcept(
 
  645        std::is_nothrow_copy_assignable<T>::value) {
 
  646        this->_assign(BSONCXX_FWD(other));
 
  650    optional_common_base& operator=(optional_common_base&& other) 
noexcept(
 
  651        std::is_nothrow_move_assignable<T>::value) {
 
  652        this->_assign(BSONCXX_FWD(other));
 
  657    void reset() noexcept {
 
  658        if (this->_has_value) {
 
  659            this->_storage.value.~T();
 
  661        this->_has_value = 
false;
 
  666    template <
typename... Args>
 
  667    T& emplace(Args&&... args) {
 
  669        this->_emplace_construct_anew(BSONCXX_FWD(args)...);
 
  670        return this->_storage.value;
 
  675    template <
typename U, 
typename... Args>
 
  676    T& emplace(std::initializer_list<U> il, Args&&... args) {
 
  678        this->_emplace_construct_anew(il, BSONCXX_FWD(args)...);
 
  679        return this->_storage.value;
 
  683    bsoncxx_cxx14_constexpr 
void swap(optional_common_base& other) 
noexcept(
 
  684        std::is_nothrow_move_constructible<T>::value&&
 
  685            bsoncxx::detail::is_nothrow_swappable<T>::value) {
 
  686        if (other._has_value) {
 
  687            if (this->_has_value) {
 
  690                swap(this->_storage.value, other._storage.value);
 
  693                this->emplace(std::move(other._storage.value));
 
  696        } 
else if (this->_has_value) {
 
  697            other.emplace(std::move(this->_storage.value));
 
  706    storage_type _storage;
 
  707    bool _has_value = 
false;
 
  711    template <
typename... Args>
 
  712    void _emplace_construct_anew(Args&&... args) 
noexcept(
 
  713        std::is_nothrow_constructible<T, Args&&...>::value) {
 
  714        new (std::addressof(this->_storage.value)) T(BSONCXX_FWD(args)...);
 
  715        this->_has_value = 
true;
 
  719    template <
typename U>
 
  720    void _assign(U&& other_storage) {
 
  721        if (other_storage._has_value) {
 
  723            if (this->_has_value) {
 
  725                this->_storage.value = BSONCXX_FWD(other_storage)._storage.value;
 
  728                this->_emplace_construct_anew(BSONCXX_FWD(other_storage)._storage.value);
 
  738struct optional_base_class {
 
  739    using type = optional_assign_base<T>;
 
  744              std::is_default_constructible<std::hash<bsoncxx::detail::remove_const_t<T>>>::value>
 
  750struct optional_hash<T, false> {
 
  751    optional_hash() = 
delete;
 
  752    optional_hash(
const optional_hash&) = 
delete;
 
  756struct optional_hash<T, true> {
 
  757    using Td = bsoncxx::detail::remove_const_t<T>;
 
  758    constexpr std::size_t operator()(
const optional<T>& opt) 
const 
  759        noexcept(
noexcept(std::hash<Td>()(std::declval<Td const&>()))) {
 
  760        return opt.has_value() ? std::hash<Td>()(*opt)  
 
  761                               : std::hash<void*>()(
nullptr);
 
  776struct hash<
bsoncxx::v_noabi::stdx::optional<T>>
 
  777    : bsoncxx::v_noabi::stdx::detail::optional_hash<T> {};
 
  782#error "Cannot find a valid polyfill for optional" 
  790using ::bsoncxx::v_noabi::stdx::in_place;
 
  791using ::bsoncxx::v_noabi::stdx::in_place_t;
 
  792using ::bsoncxx::v_noabi::stdx::make_optional;
 
  793using ::bsoncxx::v_noabi::stdx::nullopt;
 
  794using ::bsoncxx::v_noabi::stdx::nullopt_t;
 
  795using ::bsoncxx::v_noabi::stdx::optional;
 
  812#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:826
 
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.