mirror of
https://github.com/boostorg/optional.git
synced 2026-06-11 11:51:30 +02:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1fb60cb53b | |||
| ecb241a919 | |||
| ff710d113c | |||
| 88e2378c8a | |||
| fa52755c88 | |||
| 76be15bfeb | |||
| 5d8e50a9aa | |||
| 37513ddbbf | |||
| 953b678b39 | |||
| b2057c8dfe | |||
| 1c13f5f724 | |||
| aa1cf1e76c | |||
| 938502da88 | |||
| 046357ce54 |
+2
-2
@@ -1,8 +1,8 @@
|
||||
[library Boost.Optional
|
||||
[quickbook 1.4]
|
||||
[quickbook 1.7]
|
||||
[authors [Cacciola Carballal, Fernando Luis]]
|
||||
[copyright 2003-2007 Fernando Luis Cacciola Carballal]
|
||||
[copyright 2014-2026 Andrzej Krzemieński]
|
||||
[copyright 2014-2026 Andrzej Krzemieński]
|
||||
[category miscellaneous]
|
||||
[id optional]
|
||||
[dirname optional]
|
||||
|
||||
@@ -50,6 +50,18 @@ In the general case, the internal representation is something equivalent to:
|
||||
alignas(T) char _value [sizeof(T)];
|
||||
};
|
||||
|
||||
or:
|
||||
|
||||
template <typename T>
|
||||
class Optional
|
||||
{
|
||||
bool _has_value = false;
|
||||
union {
|
||||
T _value;
|
||||
DummyType _non_value;
|
||||
};
|
||||
};
|
||||
|
||||
Next, because we need to pass around these "optional" `int`s as normal `int`s,
|
||||
like returning them from functions, when copying, we need to copy `_has_value`,
|
||||
which indicates whether we have the value or not, and, if we do have value, and
|
||||
|
||||
@@ -27,7 +27,7 @@ rather than the reference itself.
|
||||
On compilers that do not conform to Standard C++ rules of reference binding,
|
||||
some operations on optional references are disabled in order to prevent subtle
|
||||
bugs. For more details see
|
||||
[link boost_optional.dependencies_and_portability.optional_reference_binding Dependencies and Portability section].
|
||||
[link optional_reference_binding Dependencies and Portability section].
|
||||
]
|
||||
|
||||
[heading Rvalue references]
|
||||
@@ -39,6 +39,8 @@ Rvalue references and lvalue references to const have the ability in C++ to exte
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[#optional_ref_rebinding_semantics]
|
||||
[section Rebinding semantics for assignment of optional references]
|
||||
|
||||
If you assign to an ['uninitialized ] `optional<T&>` the effect is to bind (for
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
[section In-Place Factories]
|
||||
[section:in_place_factories In-Place Factories][#boost_optional_factories]
|
||||
|
||||
One of the typical problems with wrappers and containers is that their
|
||||
interfaces usually provide an operation to initialize or assign the
|
||||
@@ -138,4 +138,4 @@ The factories are implemented in the headers: __IN_PLACE_FACTORY_HPP__ and __TYP
|
||||
|
||||
[caution The support for in-place factories is deprecated. Use constructor taking `in_place_init` tag and function `.emplace()` instead.]
|
||||
|
||||
[endsect]
|
||||
[endsect:in_place_factories]
|
||||
|
||||
@@ -8,7 +8,7 @@ The very minimum requirement of `optional<T>` is that `T` is a complete type and
|
||||
assert(!o); //
|
||||
o.value(); // always throws
|
||||
|
||||
But this is practically useless. In order for `optional<T>` to be able to do anything useful and offer all the spectrum of ways of accessing the contained value, `T` needs to have at least one accessible constructor. In that case you need to initialize the optional object with function `emplace()`, or if your compiler does not support it, resort to [link boost_optional.design.in_place_factories In-Place Factories]:
|
||||
But this is practically useless. In order for `optional<T>` to be able to do anything useful and offer all the spectrum of ways of accessing the contained value, `T` needs to have at least one accessible constructor. In that case you need to initialize the optional object with function `emplace()`, or if your compiler does not support it, resort to [link boost_optional_factories In-Place Factories]:
|
||||
|
||||
optional<T> o;
|
||||
o.emplace("T", "ctor", "params");
|
||||
|
||||
+14
-3
@@ -2,7 +2,7 @@
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
Copyright (c) 2015 Andrzej Krzemienski
|
||||
Copyright (c) 2015 Andrzej Krzemieński
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -15,14 +15,25 @@
|
||||
```
|
||||
namespace boost {
|
||||
|
||||
class none_t {/* see below */};
|
||||
class none_t
|
||||
{
|
||||
friend constexpr bool operator==(none_t, none_t) = default;
|
||||
/* see below */
|
||||
};
|
||||
|
||||
inline constexpr none_t none (/* see below */);
|
||||
|
||||
} // namespace boost
|
||||
```
|
||||
|
||||
Class `none_t` is meant to serve as a tag for selecting appropriate overloads of from `optional`'s interface. It is an empty, trivially copyable class with disabled default constructor.
|
||||
Class `none_t` is meant to serve as a tag for selecting appropriate overloads of from `optional`'s interface.
|
||||
It is an empty class.
|
||||
|
||||
It is [@https://en.cppreference.com/w/cpp/named_req/TriviallyCopyable.html trivially copyable].
|
||||
|
||||
It is ['not] [@https://en.cppreference.com/w/cpp/named_req/DefaultConstructible default-constructible].
|
||||
|
||||
It models concept [@https://en.cppreference.com/w/cpp/concepts/equality_comparable `std::equality_comparable`].
|
||||
|
||||
Constant `none` is used to indicate an optional object that does not contain a value in initialization, assignment and relational operations of `optional`.
|
||||
|
||||
|
||||
@@ -197,6 +197,9 @@ They are empty, trivially copyable classes with disabled default constructor.
|
||||
template<class F> constexpr auto flat_map( F f ) & -> ``['see below]``; ``[link reference_optional_flat_map __GO_TO__]``
|
||||
template<class F> constexpr auto flat_map( F f ) && -> ``['see below]``; ``[link reference_optional_flat_map_move __GO_TO__]``
|
||||
|
||||
constexpr operator optional<T&>() & noexcept; ``[link reference_optional_conversion_to_ref __GO_TO__]``
|
||||
constexpr operator optional<T const&>() const& noexcept; ``[link reference_optional_conversion_to_ref __GO_TO__]``
|
||||
|
||||
T const* get_ptr() const ; ``[link reference_optional_get_ptr __GO_TO__]``
|
||||
T* get_ptr() ; ``[link reference_optional_get_ptr __GO_TO__]``
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
Copyright (C) 2014 - 2026 Andrzej Krzemieński.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -25,31 +26,31 @@ __SPACE__
|
||||
|
||||
[: `constexpr optional<T>::optional() noexcept;`]
|
||||
|
||||
* [*Effect:] Default-Constructs an `optional`.
|
||||
* [*Postconditions:] `*this` is [_uninitialized].
|
||||
* [*Notes:] T's default constructor [_is not] called.
|
||||
* [*Postconditions:] `*this` does ['not] contain a value (is "uninitialized").
|
||||
* [*Remarks:] No contained value is initialized. For every object type `T` these constructors are core constant expressions.
|
||||
* [*Example:]
|
||||
``
|
||||
optional<T> def ;
|
||||
assert ( !def ) ;
|
||||
optional<T> oN ;
|
||||
assert ( !oN ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_constructor_none_t]
|
||||
|
||||
[#reference_optional_constructor_none_t]
|
||||
[: `constexpr optional<T>::optional( none_t ) noexcept;`]
|
||||
|
||||
* [*Effect:] Constructs an `optional` uninitialized.
|
||||
* [*Postconditions:] `*this` is [_uninitialized].
|
||||
* [*Notes:] `T`'s default constructor [_is not] called. The expression
|
||||
* [*Postconditions:] `*this` does ['not] contain a value (is "uninitialized").
|
||||
* [*Remarks:] No contained value is initialized. For every object type `T` these constructors are core constant expressions. The expression
|
||||
`boost::none` denotes an instance of `boost::none_t` that can be used as
|
||||
the parameter.
|
||||
* [*Example:]
|
||||
``
|
||||
#include <boost/none.hpp>
|
||||
|
||||
optional<T> n(none) ;
|
||||
assert ( !n ) ;
|
||||
assert ( n == none ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
@@ -281,7 +282,7 @@ factory.
|
||||
* [*Postconditions: ] `*this` is [_initialized] and its value is ['directly given]
|
||||
from the factory `f` (i.e., the value [_is not copied]).
|
||||
* [*Throws:] Whatever the `T` constructor called by the factory throws.
|
||||
* [*Notes:] See [link boost_optional.design.in_place_factories In-Place Factories]
|
||||
* [*Notes:] See [link boost_optional_factories In-Place Factories]
|
||||
* [*Exception Safety:] Exceptions can only be thrown during the call to
|
||||
the `T` constructor used by the factory; in that case, this constructor has
|
||||
no effect.
|
||||
@@ -524,7 +525,7 @@ factory.
|
||||
* [*Postconditions: ] `*this` is [_initialized] and its value is ['directly given]
|
||||
from the factory `f` (i.e., the value [_is not copied]).
|
||||
* [*Throws:] Whatever the `T` constructor called by the factory throws.
|
||||
* [*Notes:] See [link boost_optional.design.in_place_factories In-Place Factories]
|
||||
* [*Notes:] See [link boost_optional_factories In-Place Factories]
|
||||
* [*Exception Safety:] Exceptions can only be thrown during the call to
|
||||
the `T` constructor used by the factory; in that case, the `optional` object
|
||||
will be reset to be ['uninitialized].
|
||||
@@ -752,6 +753,26 @@ __SPACE__
|
||||
|
||||
__SPACE__
|
||||
|
||||
|
||||
[#reference_optional_conversion_to_ref]
|
||||
|
||||
[: `constexpr optional<T>::operator optional<T&>() & noexcept ;`]
|
||||
|
||||
* [*Returns:] If `*this` contains a value `optional<T&>(**this)`, otherwise `optional<T&>()`.
|
||||
|
||||
[: `constexpr optional<T>::operator optional<T const&>() const& noexcept ;`]
|
||||
|
||||
* [*Returns:] If `*this` contains a value `optional<T const&>(**this)`, otherwise `optional<T&>()`.
|
||||
|
||||
* [*Example:]
|
||||
``
|
||||
const optional<int> oi = 1;
|
||||
optional<const int&> ri = oi;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
|
||||
[#reference_optional_get_value_or_value]
|
||||
|
||||
[: `T const& optional<T>::get_value_or( T const& default) const ;`]
|
||||
@@ -956,7 +977,7 @@ __SPACE__
|
||||
|
||||
* [*Postconditions:] `bool(*this) == bool(rhs)`.
|
||||
|
||||
* [*Notes:] This behaviour is called ['rebinding semantics]. See [link boost_optional.design.optional_references.rebinding_semantics_for_assignment_of_optional_references here] for details.
|
||||
* [*Notes:] This behaviour is called ['rebinding semantics]. See [link optional_ref_rebinding_semantics here] for details.
|
||||
|
||||
* [*Example:]
|
||||
``
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
[section Header <boost/optional.hpp>]
|
||||
|
||||
This is an alias for header [link boost_optional.reference.header__boost_optional_optional_hpp_.header_optional_optional `<boost/optional/optional.hpp>`].
|
||||
This is an alias for header [link ref_header_optional_optional_hpp `<boost/optional/optional.hpp>`].
|
||||
|
||||
|
||||
[endsect]
|
||||
|
||||
+45
-4
@@ -13,13 +13,55 @@
|
||||
|
||||
|
||||
[section Minimum System Requirements]
|
||||
This library requires C++11 as minimum. However some features are disabled.
|
||||
This library requires C++11 as minimum. However, in C++11 some features are disabled.
|
||||
|
||||
For C++14 and higher this library provides a `constexpr` interface for non-mutable
|
||||
member functions and some mutable member functions.
|
||||
[section:constexpr Support for `constexpr`]
|
||||
|
||||
[section C++11]
|
||||
For compilers fully supporting C++11 (including unconstrained unions and ref-qualifiers),
|
||||
for trivially-destructible `T`s, `optional<T>` is a ['literal type] and its constructors
|
||||
with `this->has_value() == false` as postcondition:
|
||||
|
||||
* `optional()`,
|
||||
* `optional(none_t)`,
|
||||
|
||||
are ['core constant expressions]. Even for other `T`s, these constructors are guaranteed to
|
||||
perform ['constant initialization]: they are never subject to "initialization order fiasco".
|
||||
|
||||
Other constructors with `this->has_value() == true`
|
||||
as postcondition are core constant expressions if the expression required to initialize
|
||||
the contained value is a core constant expression. This includes constructors:
|
||||
|
||||
* `template <typename... Args> optional(in_place_init, Args&&...)`,
|
||||
* `template <typename U> optional(U&&)`,
|
||||
* `optional(const T&)`,
|
||||
* `optional(T&&)`.
|
||||
|
||||
Other constructors, including the copy and move constructos, are ['not] core constant expressions.
|
||||
|
||||
Member functions `.has_value`, `operator bool` and (non)equality comparisons with `none` are core-constant expressions for trivially-destructible `T`s.
|
||||
|
||||
Also all `const`-qualified non-static member functions and comparison operators are core constant expressions, if the corresponding operations on `T`
|
||||
are core constant expressions.
|
||||
[endsect]
|
||||
|
||||
[section C++14]
|
||||
For C++14 and higher this library, for trivially-destructible `T`s provides the `constexpr` interface for all mutable and non-mutable
|
||||
member functions, as long as:
|
||||
|
||||
* the corresponding operations on `T` are core constant expressions and
|
||||
* the member never attempts to change the `optional`'s state from not containing a value to containing a value.
|
||||
|
||||
[note For types that overload unary `operator&` (address) some member functions in `optional`, like `operator->`,
|
||||
cannot be implemented as `constexpr` on some compilers.]
|
||||
[endsect]
|
||||
|
||||
[section C++17]
|
||||
In C++17 all non-deprecated constructors are core constant expressions as long as
|
||||
`T` is a literal type and its constructor used is a core constant expression.
|
||||
[endsect]
|
||||
|
||||
[endsect:constexpr]
|
||||
|
||||
[endsect]
|
||||
|
||||
@@ -30,7 +72,6 @@ The implementation uses the following other Boost modules:
|
||||
# assert
|
||||
# config
|
||||
# core
|
||||
# static_assert
|
||||
# throw_exception
|
||||
# type_traits
|
||||
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
|
||||
[section:std_comp Comparison with `std::optional`]
|
||||
|
||||
[table
|
||||
[]
|
||||
[table Comparison with `std::optional`
|
||||
[ [[*`boost::optional`]] [[*`std::optional`]] [] ]
|
||||
[ [`optional<int> o = none;`] [`optional<int> o = nullopt;`] [Different name for no-value tag.] ]
|
||||
[ [`optional<X> o {in_place_init, a, b};`] [`optional<int> o {in_place, a, b};`] [Different name for in-place initialization tag.] ]
|
||||
@@ -42,7 +41,23 @@
|
||||
[ [`make_optional(cond, v);`] [] [No `make_optional` with condition in `std`.] ]
|
||||
[ [] [`make_optional<T>(a, b);`] [No `make_optional` with specified `T` in `boost`.] ]
|
||||
[ [`std::cout << optional<int>{};`] [] [No printing to IOStreams in `std`.]]
|
||||
|
||||
[ [`std::vector<optional<int>> rng;`
|
||||
|
||||
`std::ranges::find(rng, boost::none)`] [`std::vector<optional<int>> rng;`
|
||||
|
||||
`std::ranges::find(rng, boost::optional<int>{})`] [optional<T> is never [@https://en.cppreference.com/w/cpp/concepts/equality_comparable `std::equality_comparable_with`] `nullopt_t` in `std`. ] ]
|
||||
|
||||
[ [```
|
||||
void test(vector<optional<T>> rng, T val) {
|
||||
std::ranges::find(rng, val);
|
||||
}
|
||||
```] [```
|
||||
void test(vector<optional<T>> rng, T val) {
|
||||
std::ranges::find(rng, make_optional(val));
|
||||
}
|
||||
```] [For `std::optional`, code without `make_optional()` compiles but is ['undefined behavior] when `T` is itself an `optional`. ] ]
|
||||
|
||||
]
|
||||
|
||||
|
||||
[endsect][/ std_comp]
|
||||
|
||||
@@ -11,9 +11,60 @@
|
||||
|
||||
[section:relnotes Release Notes]
|
||||
|
||||
[heading Boost Release 1.xx]
|
||||
|
||||
* Fixed regression in the copy-initialization of `optional<bool>`. This fixes [@https://github.com/boostorg/optional/issues/146 issue #146].
|
||||
|
||||
[heading Boost Release 1.91]
|
||||
|
||||
* For compilers with full C++11 support (including "unrestricted unions" and ref-qualifiers)
|
||||
changed the implementation from aligned storage to union storage. This enables the gradual
|
||||
`constexpr` support:
|
||||
|
||||
* In C++11, some constructors and `const`-qualified accessors become usable
|
||||
in compile-time contexts (are ['core constant expressions]) for types
|
||||
satisfying certain constraints.
|
||||
* In C++14 even some mutating operations become core constant expressions (those
|
||||
that do not require changing the state of `optional` from not having a value to
|
||||
having a value), for co-operating types.
|
||||
* In C++17 all constructors (including copy and move) become core constant expressions
|
||||
for co-operating types.
|
||||
|
||||
This addresses issues [@https://github.com/boostorg/optional/issues/132 #132] and [@https://github.com/boostorg/optional/issues/143 #143].
|
||||
|
||||
* *Breaking change.* In the said implementation, abandoned the mechanism for customizing
|
||||
`swap`. Hardly anyone knows about this mechanism and it was never documented.
|
||||
|
||||
* In the said implementation, applied a couple of small changes to get closer to the interface of `std::optional`:
|
||||
* Enabled syntax `o = {}` for putting optional objects to no-value state.
|
||||
* Enabled syntax `o.value_or({})`, which uses a default-constructed `T`.
|
||||
* Construct `o = u`, where `o` is of type `optional<T>` and `u` is of type `U` convertible to `T`,
|
||||
does not create a temporary `T`.
|
||||
|
||||
* In the said implementation, added a conversion from `optional<T>&` to `optional<T&>`. This addresses [@https://github.com/boostorg/optional/issues/142 issue #142].
|
||||
|
||||
* `none_t` is now `std::equality_comparable`, which means that `none_t` and `optional<T>`
|
||||
model concept `std::equality_comparable_with` (for `std::equality_comparable` `T`s),
|
||||
which means that you can `std::ranges::find(rng, boost::none)` for a range of optional objects.
|
||||
|
||||
* *Warning.* In the future releases we intend to introduce the range interface
|
||||
in `optional`, so that `std::ranges::range<optional<T>>` will be `true`.
|
||||
This may affect the overload resolution in programs that make decisions based
|
||||
on predicates such as `std::ranges::range`. For instance, the following code
|
||||
will start behaving differently:
|
||||
|
||||
```
|
||||
template <typename T>
|
||||
void serialize(T const& v)
|
||||
{
|
||||
if constexpr (std::ranges::range<T>)
|
||||
serialize_as_range(v);
|
||||
else if constexpr (custom::is_optional_like<T>)
|
||||
serialize_as_optional(v);
|
||||
else
|
||||
serialize_as_value(v);
|
||||
}
|
||||
```
|
||||
|
||||
[heading Boost Release 1.87]
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#elif defined(BOOST_NO_CXX11_REF_QUALIFIERS) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DEFAULTED_MOVES)
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Optional 1.83 and will be removed in Boost.Optional 1.88.")
|
||||
BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Optional 1.83 and will be removed in Boost.Optional 1.92.")
|
||||
|
||||
#endif
|
||||
|
||||
@@ -46,6 +46,11 @@ struct none_t
|
||||
{
|
||||
struct init_tag{};
|
||||
explicit BOOST_CONSTEXPR none_t(init_tag){} // to disable default constructor
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DISABLE_EQUALITY_FOR_NONE
|
||||
friend BOOST_CONSTEXPR bool operator==(none_t, none_t) { return true; }
|
||||
friend BOOST_CONSTEXPR bool operator!=(none_t, none_t) { return false; }
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // old implementation workarounds
|
||||
|
||||
@@ -22,14 +22,22 @@
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/addressof.hpp>
|
||||
#include <type_traits>
|
||||
#include <boost/optional/detail/optional_factory_support.hpp>
|
||||
|
||||
#ifndef BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
#ifndef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
#include <boost/type_traits/decay.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
#endif
|
||||
|
||||
// This is needed for C++11, where constexpr functions must contain a single expression.
|
||||
// We want to assert and then return.
|
||||
#if defined NDEBUG
|
||||
# define BOOST_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
|
||||
#else
|
||||
# define BOOST_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{BOOST_ASSERT(!(#CHECK));}(), (EXPR)))
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX14_CONSTEXPR
|
||||
#ifdef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
# define BOOST_OPTIONAL_DECAY(T) typename ::std::decay<T>::type
|
||||
# define BOOST_OPTIONAL_IS_TAGGED(TAG, U) ::std::is_base_of<TAG, BOOST_OPTIONAL_DECAY(U)>
|
||||
#else
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP
|
||||
|
||||
#ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT
|
||||
#ifndef BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
#ifndef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/type_traits/is_const.hpp>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
#ifdef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
# define BOOST_OPTIONAL_TT_PREFIX ::std
|
||||
#else
|
||||
# define BOOST_OPTIONAL_TT_PREFIX boost
|
||||
@@ -135,27 +135,27 @@ public:
|
||||
typedef T* pointer_type;
|
||||
typedef T* pointer_const_type;
|
||||
|
||||
BOOST_CXX14_CONSTEXPR optional() BOOST_NOEXCEPT : ptr_() {}
|
||||
BOOST_CXX14_CONSTEXPR optional(none_t) BOOST_NOEXCEPT : ptr_() {}
|
||||
BOOST_CONSTEXPR optional() BOOST_NOEXCEPT : ptr_() {}
|
||||
BOOST_CONSTEXPR optional(none_t) BOOST_NOEXCEPT : ptr_() {}
|
||||
|
||||
template <class U>
|
||||
BOOST_CXX14_CONSTEXPR explicit optional(const optional<U&>& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {}
|
||||
BOOST_CXX14_CONSTEXPR optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {}
|
||||
BOOST_CONSTEXPR explicit optional(const optional<U&>& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {}
|
||||
BOOST_CONSTEXPR optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {}
|
||||
|
||||
// the following two implement a 'conditionally explicit' constructor: condition is a hack for buggy compilers with screwed conversion construction from const int
|
||||
template <class U,
|
||||
BOOST_OPTIONAL_REQUIRES(detail::is_same_decayed<T, U>),
|
||||
BOOST_OPTIONAL_REQUIRES(detail::is_const_integral_bad_for_conversion<U>)>
|
||||
BOOST_CXX14_CONSTEXPR explicit
|
||||
optional(U& rhs) BOOST_NOEXCEPT
|
||||
: ptr_(boost::addressof(rhs)) {}
|
||||
BOOST_CONSTEXPR explicit
|
||||
optional(U& rhs) BOOST_NOEXCEPT
|
||||
: ptr_(boost::addressof(rhs)) {}
|
||||
|
||||
template <class U,
|
||||
BOOST_OPTIONAL_REQUIRES(detail::is_same_decayed<T, U>),
|
||||
BOOST_OPTIONAL_REQUIRES(!detail::is_const_integral_bad_for_conversion<U>)>
|
||||
BOOST_CXX14_CONSTEXPR
|
||||
optional(U& rhs) BOOST_NOEXCEPT
|
||||
: ptr_(boost::addressof(rhs)) {}
|
||||
BOOST_CONSTEXPR
|
||||
optional(U& rhs) BOOST_NOEXCEPT
|
||||
: ptr_(boost::addressof(rhs)) {}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; }
|
||||
template <class U>
|
||||
@@ -164,50 +164,47 @@ public:
|
||||
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void swap(optional& rhs) BOOST_NOEXCEPT { ::std::swap(ptr_, rhs.ptr_); }
|
||||
BOOST_CXX14_CONSTEXPR T& get() const { BOOST_ASSERT(ptr_); return *ptr_; }
|
||||
constexpr T& get() const { return BOOST_OPTIONAL_ASSERTED_EXPRESSION(ptr_, *ptr_); }
|
||||
|
||||
BOOST_CXX14_CONSTEXPR T* get_ptr() const BOOST_NOEXCEPT { return ptr_; }
|
||||
BOOST_CXX14_CONSTEXPR T* operator->() const { BOOST_ASSERT(ptr_); return ptr_; }
|
||||
BOOST_CXX14_CONSTEXPR T& operator*() const { BOOST_ASSERT(ptr_); return *ptr_; }
|
||||
constexpr T* get_ptr() const BOOST_NOEXCEPT { return ptr_; }
|
||||
constexpr T* operator->() const { return BOOST_OPTIONAL_ASSERTED_EXPRESSION(ptr_, ptr_); }
|
||||
constexpr T& operator*() const { return BOOST_OPTIONAL_ASSERTED_EXPRESSION(ptr_, *ptr_); }
|
||||
|
||||
BOOST_CXX14_CONSTEXPR T& value() const
|
||||
constexpr T& value() const
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return this->get();
|
||||
else
|
||||
boost::throw_exception(boost::bad_optional_access());
|
||||
return this->is_initialized() ?
|
||||
this->get() :
|
||||
(boost::throw_exception(boost::bad_optional_access()), this->get());
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR explicit operator bool() const BOOST_NOEXCEPT { return ptr_ != 0; }
|
||||
constexpr explicit operator bool() const BOOST_NOEXCEPT { return ptr_ != 0; }
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void reset() BOOST_NOEXCEPT { ptr_ = 0; }
|
||||
|
||||
BOOST_CXX14_CONSTEXPR bool is_initialized() const BOOST_NOEXCEPT { return ptr_ != 0; }
|
||||
BOOST_CXX14_CONSTEXPR bool has_value() const BOOST_NOEXCEPT { return ptr_ != 0; }
|
||||
constexpr bool is_initialized() const BOOST_NOEXCEPT { return ptr_ != 0; }
|
||||
constexpr bool has_value() const BOOST_NOEXCEPT { return ptr_ != 0; }
|
||||
|
||||
template <typename F>
|
||||
BOOST_CXX14_CONSTEXPR optional<typename optional_detail::result_of<F, reference_const_type>::type>
|
||||
constexpr optional<typename optional_detail::result_of<F, reference_const_type>::type>
|
||||
map(F f) const
|
||||
{
|
||||
if (this->has_value())
|
||||
return f(this->get());
|
||||
else
|
||||
return none;
|
||||
return this->has_value() ?
|
||||
f(get()) :
|
||||
optional<typename optional_detail::result_of<F, reference_const_type>::type>();
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
BOOST_CXX14_CONSTEXPR optional<typename optional_detail::result_value_type<F, reference_const_type>::type>
|
||||
constexpr optional<typename optional_detail::result_value_type<F, reference_const_type>::type>
|
||||
flat_map(F f) const
|
||||
{
|
||||
if (this->has_value())
|
||||
return f(get());
|
||||
else
|
||||
return none;
|
||||
return this->has_value() ?
|
||||
f(get()) :
|
||||
optional<typename optional_detail::result_value_type<F, reference_const_type>::type>();
|
||||
}
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
|
||||
BOOST_CXX14_CONSTEXPR optional(T&& /* rhs */) BOOST_NOEXCEPT { detail::prevent_binding_rvalue<T&&>(); }
|
||||
optional(T&& /* rhs */) BOOST_NOEXCEPT { detail::prevent_binding_rvalue<T&&>(); }
|
||||
|
||||
template <class R, BOOST_OPTIONAL_REQUIRES(detail::no_unboxing_cond<T, R>)>
|
||||
BOOST_CXX14_CONSTEXPR optional(R&& r) BOOST_NOEXCEPT
|
||||
|
||||
@@ -25,32 +25,32 @@ namespace boost {
|
||||
//
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator == ( optional<T> const& x, optional<T> const& y )
|
||||
{ return bool(x) && bool(y) ? *x == *y : bool(x) == bool(y); }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator < ( optional<T> const& x, optional<T> const& y )
|
||||
{ return !y ? false : (!x ? true : (*x) < (*y)); }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator != ( optional<T> const& x, optional<T> const& y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator > ( optional<T> const& x, optional<T> const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator <= ( optional<T> const& x, optional<T> const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator >= ( optional<T> const& x, optional<T> const& y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
@@ -59,32 +59,32 @@ bool operator >= ( optional<T> const& x, optional<T> const& y )
|
||||
// optional<T> vs T cases
|
||||
//
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator == ( optional<T> const& x, T const& y )
|
||||
{ return x && (*x == y); }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator < ( optional<T> const& x, T const& y )
|
||||
{ return (!x) || (*x < y); }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator != ( optional<T> const& x, T const& y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator > ( optional<T> const& x, T const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator <= ( optional<T> const& x, T const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator >= ( optional<T> const& x, T const& y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
@@ -93,32 +93,32 @@ bool operator >= ( optional<T> const& x, T const& y )
|
||||
//
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator == ( T const& x, optional<T> const& y )
|
||||
{ return y && (x == *y); }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator < ( T const& x, optional<T> const& y )
|
||||
{ return y && (x < *y); }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator != ( T const& x, optional<T> const& y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator > ( T const& x, optional<T> const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator <= ( T const& x, optional<T> const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator >= ( T const& x, optional<T> const& y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
@@ -128,32 +128,32 @@ bool operator >= ( T const& x, optional<T> const& y )
|
||||
//
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator == ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
|
||||
{ return !x; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator < ( optional<T> const&, none_t ) BOOST_NOEXCEPT
|
||||
{ return false; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator != ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
|
||||
{ return bool(x); }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator > ( optional<T> const& x, none_t y ) BOOST_NOEXCEPT
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator <= ( optional<T> const& x, none_t y ) BOOST_NOEXCEPT
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator >= ( optional<T> const& x, none_t y ) BOOST_NOEXCEPT
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
@@ -162,32 +162,32 @@ bool operator >= ( optional<T> const& x, none_t y ) BOOST_NOEXCEPT
|
||||
//
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator == ( none_t , optional<T> const& y ) BOOST_NOEXCEPT
|
||||
{ return !y; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator < ( none_t , optional<T> const& y ) BOOST_NOEXCEPT
|
||||
{ return bool(y); }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator != ( none_t, optional<T> const& y ) BOOST_NOEXCEPT
|
||||
{ return bool(y); }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator > ( none_t x, optional<T> const& y ) BOOST_NOEXCEPT
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator <= ( none_t x, optional<T> const& y ) BOOST_NOEXCEPT
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator >= ( none_t x, optional<T> const& y ) BOOST_NOEXCEPT
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2026 Andrzej Krzemieński.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
//
|
||||
//
|
||||
// This header provides definitions required by any specialization of
|
||||
// optional<>.
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_SELECT_IMPLEMENTATION_01FEB2026_HPP
|
||||
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_SELECT_IMPLEMENTATION_01FEB2026_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_CONSTEXPR) && \
|
||||
!defined(BOOST_NO_CXX11_REF_QUALIFIERS) && \
|
||||
!defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \
|
||||
!defined(BOOST_NO_CXX11_UNRESTRICTED_UNION) && \
|
||||
!defined(BOOST_NO_CXX11_NOEXCEPT) && \
|
||||
!defined(BOOST_NO_CXX11_DEFAULTED_MOVES) && \
|
||||
!defined(BOOST_OPTIONAL_CONFIG_DISABLE_UNION_OPTIONAL)
|
||||
# define BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
|
||||
// In C++20 we have `std::construct_at()` which is a constexpr equivalent of
|
||||
// placement-new. We can then make more functions constexpr.
|
||||
// TBD: This additional constexpr-ication is left for the future.
|
||||
# define BOOST_OPTIONAL_CXX20_CONSTEXPR
|
||||
|
||||
#endif //BOOST_OPTIONAL_DETAIL_OPTIONAL_SELECT_IMPLEMENTATION_01FEB2026_HPP
|
||||
+228
-86
@@ -13,13 +13,12 @@
|
||||
// This header provides definitions required by any specialization of
|
||||
// optional<>.
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_CONSTEXPR_OPTIONAL_01FEB2026_HPP
|
||||
#define BOOST_OPTIONAL_DETAIL_CONSTEXPR_OPTIONAL_01FEB2026_HPP
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_UNION_OPTIONAL_01FEB2026_HPP
|
||||
#define BOOST_OPTIONAL_DETAIL_UNION_OPTIONAL_01FEB2026_HPP
|
||||
|
||||
#include <initializer_list>
|
||||
//#include <initializer_list>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/invoke_swap.hpp>
|
||||
#include <boost/core/invoke_swap.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/optional/bad_optional_access.hpp>
|
||||
|
||||
@@ -30,12 +29,20 @@
|
||||
# define BOOST_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false
|
||||
|
||||
|
||||
// In C++20 we have `std::construct_at()` which is a constexpr equivalent of
|
||||
// placement-new. We can then make more functions constexpr.
|
||||
// TBD: This additional constexpr-ication is left for the future.
|
||||
# define BOOST_OPTIONAL_CXX20_CONSTEXPR
|
||||
# ifdef __cpp_guaranteed_copy_elision
|
||||
# if __cpp_guaranteed_copy_elision
|
||||
# define BOOST_OPTIONAL_CONSTEXPR_COPY
|
||||
# endif
|
||||
# endif
|
||||
|
||||
|
||||
template <typename T, typename U>
|
||||
struct fail_hard_on_nonconvertible
|
||||
{
|
||||
static_assert(::std::is_convertible<U&&, T>::value, "The argument must be convertible to T");
|
||||
using type = bool;
|
||||
};
|
||||
|
||||
// Missing C++17 type traits
|
||||
namespace boost { namespace optional_detail {
|
||||
|
||||
@@ -47,7 +54,7 @@ struct conjunction<B1> : B1 {};
|
||||
|
||||
template <class B1, class... Bn>
|
||||
struct conjunction<B1, Bn...>
|
||||
: ::std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};
|
||||
: ::std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
|
||||
|
||||
}}
|
||||
|
||||
@@ -67,9 +74,20 @@ union constexpr_union_storage_t
|
||||
|
||||
constexpr constexpr_union_storage_t( trivial_init_t ) noexcept : dummy_() {};
|
||||
|
||||
#if defined(BOOST_GCC) && (__GNUC__ >= 7)
|
||||
// false positive, see https://github.com/boostorg/variant2/issues/55,
|
||||
// https://github.com/boostorg/url/issues/979
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
template <class... Args>
|
||||
constexpr constexpr_union_storage_t( Args&&... args ) : value_(forward_<Args>(args)...) {}
|
||||
|
||||
#if defined(BOOST_GCC) && (__GNUC__ >= 7)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
//~constexpr_union_storage_t() = default; // No need to destroy a trivially-destructible type
|
||||
};
|
||||
|
||||
@@ -81,9 +99,20 @@ union fallback_union_storage_t
|
||||
|
||||
constexpr fallback_union_storage_t( trivial_init_t ) noexcept : dummy_() {};
|
||||
|
||||
#if defined(BOOST_GCC) && (__GNUC__ >= 7)
|
||||
// false positive, see https://github.com/boostorg/variant2/issues/55,
|
||||
// https://github.com/boostorg/url/issues/979
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
template <class... Args>
|
||||
constexpr fallback_union_storage_t( Args&&... args ) : value_(forward_<Args>(args)...) {}
|
||||
|
||||
#if defined(BOOST_GCC) && (__GNUC__ >= 7)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
~fallback_union_storage_t(){} // My owner will destroy the `T` if needed.
|
||||
// Cannot default in a union with nontrivial `T`.
|
||||
};
|
||||
@@ -108,13 +137,22 @@ struct constexpr_guarded_storage
|
||||
template <class... Args> explicit constexpr constexpr_guarded_storage(optional_ns::in_place_init_t, Args&&... args)
|
||||
: init_(true), storage_(forward_<Args>(args)...) {}
|
||||
|
||||
template <class U, class... Args, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
|
||||
constexpr explicit constexpr_guarded_storage(optional_ns::in_place_init_t, ::std::initializer_list<U> il, Args&&... args)
|
||||
: init_(true), storage_(il, forward_<Args>(args)...) {}
|
||||
// template <class U, class... Args, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
|
||||
// constexpr explicit constexpr_guarded_storage(optional_ns::in_place_init_t, ::std::initializer_list<U> il, Args&&... args)
|
||||
// : init_(true), storage_(il, forward_<Args>(args)...) {}
|
||||
|
||||
constexpr void reset () noexcept { init_ = false; }
|
||||
BOOST_CXX14_CONSTEXPR void reset () noexcept { init_ = false; }
|
||||
|
||||
~constexpr_guarded_storage() = default;
|
||||
//~constexpr_guarded_storage() = default;
|
||||
|
||||
#if (defined(_MSC_VER) && 1910 <= _MSC_VER && _MSC_VER <= 1916)
|
||||
// Workaround for MSVC 14.1x bug where it eagerly tries to define the copy/move operations
|
||||
// these are declared but never defined
|
||||
constexpr_guarded_storage(const constexpr_guarded_storage&);
|
||||
constexpr_guarded_storage(constexpr_guarded_storage&&);
|
||||
constexpr_guarded_storage& operator=(const constexpr_guarded_storage&);
|
||||
constexpr_guarded_storage& operator=(constexpr_guarded_storage&&);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -130,12 +168,12 @@ struct fallback_guarded_storage
|
||||
|
||||
explicit constexpr fallback_guarded_storage(T&& v) : init_(true), storage_(move_(v)) {}
|
||||
|
||||
template <class... Args> explicit fallback_guarded_storage(optional_ns::in_place_init_t, Args&&... args)
|
||||
template <class... Args> explicit constexpr fallback_guarded_storage(optional_ns::in_place_init_t, Args&&... args)
|
||||
: init_(true), storage_(forward_<Args>(args)...) {}
|
||||
|
||||
template <class U, class... Args, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
|
||||
explicit fallback_guarded_storage(optional_ns::in_place_init_t, ::std::initializer_list<U> il, Args&&... args)
|
||||
: init_(true), storage_(il, forward_<Args>(args)...) {}
|
||||
// template <class U, class... Args, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
|
||||
// explicit fallback_guarded_storage(optional_ns::in_place_init_t, ::std::initializer_list<U> il, Args&&... args)
|
||||
// : init_(true), storage_(il, forward_<Args>(args)...) {}
|
||||
|
||||
void reset() noexcept
|
||||
{
|
||||
@@ -148,6 +186,15 @@ struct fallback_guarded_storage
|
||||
}
|
||||
|
||||
~fallback_guarded_storage() { if (init_) storage_.value_.T::~T(); }
|
||||
|
||||
#if (defined(_MSC_VER) && 1910 <= _MSC_VER && _MSC_VER <= 1916)
|
||||
// Workaround for MSVC 14.1x bug where it eagerly tries to define the copy/move operations
|
||||
// These are declared but never defined
|
||||
fallback_guarded_storage(const fallback_guarded_storage&);
|
||||
fallback_guarded_storage(fallback_guarded_storage&&);
|
||||
fallback_guarded_storage& operator=(const fallback_guarded_storage&);
|
||||
fallback_guarded_storage& operator=(fallback_guarded_storage&&);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -169,16 +216,16 @@ namespace boost {
|
||||
{
|
||||
using storage_t = optional_detail::guarded_storage<T>;
|
||||
storage_t storage;
|
||||
static_assert( !::std::is_same<typename std::decay<T>::type, none_t>::value, "bad T" );
|
||||
static_assert( !::std::is_same<typename std::decay<T>::type, in_place_init_t>::value, "bad T" );
|
||||
static_assert( !::std::is_same<typename std::decay<T>::type, none_t>::value, "optional<none_t> is illegal" );
|
||||
static_assert( !::std::is_same<typename std::decay<T>::type, in_place_init_t>::value, "optional<in_place_init_t> is illegal" );
|
||||
static_assert( !::std::is_same<typename std::decay<T>::type, in_place_init_if_t>::value, "optional<in_place_init_if_t> is illegal" );
|
||||
|
||||
|
||||
constexpr typename ::std::remove_const<T>::type* dataptr() { return ::boost::addressof(storage.storage_.value_); }
|
||||
BOOST_CXX14_CONSTEXPR typename ::std::remove_const<T>::type* dataptr() { return ::boost::addressof(storage.storage_.value_); }
|
||||
constexpr const T* dataptr() const { return ::boost::addressof(storage.storage_.value_); }
|
||||
|
||||
constexpr const T& contained_val() const& { return storage.storage_.value_; }
|
||||
constexpr T&& contained_val() && { return optional_detail::move_(storage.storage_.value_); }
|
||||
constexpr T& contained_val() & { return storage.storage_.value_; }
|
||||
BOOST_CXX14_CONSTEXPR T&& contained_val() && { return optional_detail::move_(storage.storage_.value_); }
|
||||
BOOST_CXX14_CONSTEXPR T& contained_val() & { return storage.storage_.value_; }
|
||||
|
||||
template <typename... Args>
|
||||
BOOST_OPTIONAL_CXX20_CONSTEXPR void initialize(Args&&... args)
|
||||
@@ -188,6 +235,31 @@ namespace boost {
|
||||
storage.init_ = true;
|
||||
}
|
||||
|
||||
#ifdef BOOST_OPTIONAL_CONSTEXPR_COPY
|
||||
// The conditional initialization of storage needs to employ a factory
|
||||
// function, so that we can utilize the guaranteed copy elision on the
|
||||
// return type.
|
||||
// an alternative -- using a conditional operator in the initializer --
|
||||
// does not work in MSVC 14.2 and 14.3.
|
||||
template <typename... U>
|
||||
static constexpr storage_t conditional_storage_from_values(bool cond, U&&... v)
|
||||
{
|
||||
if (cond)
|
||||
return storage_t(in_place_init, optional_detail::forward_<U>(v)...);
|
||||
else
|
||||
return storage_t();
|
||||
}
|
||||
|
||||
template <typename OU>
|
||||
static constexpr storage_t conditional_storage_from_optional(OU&& ou)
|
||||
{
|
||||
if (ou.has_value())
|
||||
return storage_t(in_place_init, *optional_detail::forward_<OU>(ou));
|
||||
else
|
||||
return storage_t();
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
using unqualified_value_type = typename ::std::remove_const<T>::type;
|
||||
@@ -209,36 +281,97 @@ namespace boost {
|
||||
constexpr optional(const T& v) : storage(v) {}
|
||||
constexpr optional(T&& v) : storage(optional_detail::move_(v)) {}
|
||||
|
||||
#ifdef BOOST_OPTIONAL_CONSTEXPR_COPY
|
||||
constexpr optional(bool cond, const T& v)
|
||||
: storage(cond ? storage_t(v) : storage_t())
|
||||
: storage(conditional_storage_from_values(cond, v))
|
||||
{}
|
||||
|
||||
constexpr optional(bool cond, T&& v)
|
||||
: storage(cond ? storage_t(optional_detail::move_(v)) : storage_t())
|
||||
: storage(conditional_storage_from_values(cond, optional_detail::move_(v)))
|
||||
{}
|
||||
|
||||
constexpr optional(const optional& rhs)
|
||||
: storage(rhs.is_initialized() ? storage_t(*rhs) : storage_t())
|
||||
: storage(conditional_storage_from_optional(rhs))
|
||||
{}
|
||||
|
||||
constexpr optional(optional&& rhs)
|
||||
noexcept(::std::is_nothrow_move_constructible<T>::value)
|
||||
: storage(rhs.is_initialized() ? storage_t(*optional_detail::move_(rhs)) : storage_t())
|
||||
: storage(conditional_storage_from_optional(optional_detail::move_(rhs)))
|
||||
{}
|
||||
|
||||
template <typename U, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U const&>)>
|
||||
constexpr explicit optional(optional<U> const& rhs)
|
||||
: storage(rhs.is_initialized() ? storage_t(*rhs) : storage_t())
|
||||
: storage(conditional_storage_from_optional(rhs))
|
||||
{}
|
||||
|
||||
template <typename U, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U&&>)>
|
||||
constexpr explicit optional(optional<U> && rhs)
|
||||
: storage(rhs.is_initialized() ? storage_t(*optional_detail::move_(rhs)) : storage_t())
|
||||
: storage(conditional_storage_from_optional(optional_detail::move_(rhs)))
|
||||
{}
|
||||
|
||||
template <typename... Args>
|
||||
constexpr explicit optional( in_place_init_if_t, bool cond, Args&&... args )
|
||||
: storage(conditional_storage_from_values(cond, optional_detail::forward_<Args>(args)...))
|
||||
{}
|
||||
#else
|
||||
optional(bool cond, const T& v)
|
||||
: storage()
|
||||
{
|
||||
if (cond)
|
||||
initialize(v);
|
||||
}
|
||||
|
||||
optional(bool cond, T&& v)
|
||||
: storage()
|
||||
{
|
||||
if (cond)
|
||||
initialize(optional_detail::move_(v));
|
||||
}
|
||||
|
||||
optional(const optional& rhs)
|
||||
: storage()
|
||||
{
|
||||
if (rhs.is_initialized())
|
||||
initialize(*rhs);
|
||||
}
|
||||
|
||||
optional(optional&& rhs)
|
||||
noexcept(::std::is_nothrow_move_constructible<T>::value)
|
||||
: storage()
|
||||
{
|
||||
if (rhs.is_initialized())
|
||||
initialize(*optional_detail::move_(rhs));
|
||||
}
|
||||
|
||||
template <typename U, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U const&>)>
|
||||
explicit optional(optional<U> const& rhs)
|
||||
: storage()
|
||||
{
|
||||
if (rhs.is_initialized())
|
||||
initialize(*rhs);
|
||||
}
|
||||
|
||||
template <typename U, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U&&>)>
|
||||
explicit optional(optional<U> && rhs)
|
||||
: storage()
|
||||
{
|
||||
if (rhs.is_initialized())
|
||||
initialize(*optional_detail::move_(rhs));
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
explicit optional( in_place_init_if_t, bool cond, Args&&... args )
|
||||
: storage()
|
||||
{
|
||||
if (cond)
|
||||
initialize(optional_detail::forward_<Args>(args)...);
|
||||
}
|
||||
#endif // BOOST_OPTIONAL_CONSTEXPR_COPY
|
||||
|
||||
template <typename FT,
|
||||
BOOST_OPTIONAL_REQUIRES(optional_detail::is_typed_in_place_factory<FT>)>
|
||||
constexpr explicit optional (FT&& factory)
|
||||
/*non-constexpr (deprecated)*/
|
||||
explicit optional (FT&& factory)
|
||||
: storage()
|
||||
{
|
||||
factory.apply(this->dataptr());
|
||||
@@ -247,15 +380,20 @@ namespace boost {
|
||||
|
||||
template <typename FT,
|
||||
BOOST_OPTIONAL_REQUIRES(optional_detail::is_in_place_factory<FT>)>
|
||||
constexpr explicit optional (FT&& factory)
|
||||
/*non-constexpr (deprecated)*/
|
||||
explicit optional (FT&& factory)
|
||||
: storage()
|
||||
{
|
||||
factory.template apply<T>(this->dataptr());
|
||||
boost_optional_detail::construct<value_type>(factory, this->dataptr());
|
||||
storage.init_ = true;
|
||||
}
|
||||
|
||||
template <typename U,
|
||||
BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U&&>)>
|
||||
BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U&&>),
|
||||
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_typed_in_place_factory<U>),
|
||||
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_in_place_factory<U>),
|
||||
BOOST_OPTIONAL_REQUIRES(!BOOST_OPTIONAL_IS_TAGGED(optional_detail::optional_tag, U))
|
||||
>
|
||||
constexpr explicit optional(U&& v)
|
||||
: storage(optional_ns::in_place_init, optional_detail::forward_<U>(v))
|
||||
{}
|
||||
@@ -265,12 +403,21 @@ namespace boost {
|
||||
: storage(in_place_init, optional_detail::forward_<Args>(args)...)
|
||||
{}
|
||||
|
||||
template <typename... Args>
|
||||
constexpr explicit optional( in_place_init_if_t, bool cond, Args&&... args )
|
||||
: storage( cond ? storage_t(in_place_init, optional_detail::forward_<Args>(args)...) : storage_t() )
|
||||
{}
|
||||
BOOST_CXX14_CONSTEXPR operator optional<T&>() & noexcept
|
||||
{
|
||||
return this->has_value() ? optional<T&>(**this) : optional<T&>();
|
||||
}
|
||||
|
||||
constexpr void reset() noexcept
|
||||
BOOST_CONSTEXPR operator optional<const T&>() const& noexcept
|
||||
{
|
||||
return this->has_value() ? optional<const T&>(**this) : optional<const T&>();
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR operator optional<T&>() && noexcept = delete;
|
||||
BOOST_CONSTEXPR operator optional<const T&>() const&& noexcept = delete;
|
||||
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void reset() noexcept
|
||||
{
|
||||
storage.reset();
|
||||
}
|
||||
@@ -283,13 +430,13 @@ namespace boost {
|
||||
template <typename... Args>
|
||||
BOOST_OPTIONAL_CXX20_CONSTEXPR void emplace(Args&&... args)
|
||||
{
|
||||
reset(); static_assert(noexcept(reset()));
|
||||
reset();
|
||||
// <-- now we are not containing a value
|
||||
initialize(optional_detail::forward_<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
constexpr optional& operator=(none_t) noexcept
|
||||
BOOST_CXX14_CONSTEXPR optional& operator=(none_t) noexcept
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
@@ -374,7 +521,9 @@ namespace boost {
|
||||
BOOST_OPTIONAL_REQUIRES(!::std::is_same<typename ::std::decay<U>::type, optional>),
|
||||
BOOST_OPTIONAL_REQUIRES(!optional_detail::conjunction<::std::is_scalar<T>, ::std::is_same<T, BOOST_OPTIONAL_DECAY(U)>>),
|
||||
BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U>),
|
||||
BOOST_OPTIONAL_REQUIRES(::std::is_assignable<T&, U>)
|
||||
BOOST_OPTIONAL_REQUIRES(::std::is_assignable<T&, U>),
|
||||
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_typed_in_place_factory<U>),
|
||||
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_in_place_factory<U>)
|
||||
>
|
||||
BOOST_OPTIONAL_CXX20_CONSTEXPR optional& operator=(U&& v)
|
||||
{
|
||||
@@ -386,15 +535,17 @@ namespace boost {
|
||||
}
|
||||
|
||||
template <class F, BOOST_OPTIONAL_REQUIRES(optional_detail::is_in_place_factory<F>)>
|
||||
/*non-constexpr (deprecated)*/
|
||||
optional& operator=(F&& factory)
|
||||
{
|
||||
reset();
|
||||
factory.template apply<T>(this->dataptr());
|
||||
boost_optional_detail::construct<value_type>(factory, this->dataptr());
|
||||
storage.init_ = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class F, BOOST_OPTIONAL_REQUIRES(optional_detail::is_typed_in_place_factory<F>)>
|
||||
/*non-constexpr (deprecated)*/
|
||||
optional& operator=(F&& factory)
|
||||
{
|
||||
reset();
|
||||
@@ -406,7 +557,6 @@ namespace boost {
|
||||
BOOST_OPTIONAL_CXX20_CONSTEXPR
|
||||
void swap(optional& rhs)
|
||||
noexcept(::std::is_nothrow_move_constructible<T>::value && noexcept(boost::core::invoke_swap(*rhs, *rhs)))
|
||||
// I am cheating here. I need "swapabe" not "assignnable" trait. But this is best I can do in C++14
|
||||
{
|
||||
if (is_initialized())
|
||||
{
|
||||
@@ -428,8 +578,8 @@ namespace boost {
|
||||
constexpr bool has_value() const noexcept { return this->is_initialized(); }
|
||||
constexpr explicit operator bool() const noexcept { return this->is_initialized(); }
|
||||
|
||||
constexpr reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->contained_val(); }
|
||||
constexpr reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->contained_val(); }
|
||||
constexpr reference_const_type get() const { return BOOST_OPTIONAL_ASSERTED_EXPRESSION(this->is_initialized(), this->contained_val()); }
|
||||
BOOST_CXX14_CONSTEXPR reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->contained_val(); }
|
||||
|
||||
//BOOST_DEPRECATED("use `value_or(v)` instead")
|
||||
reference_const_type get_value_or (reference_const_type v) const { return this->is_initialized() ? this->contained_val() : v; }
|
||||
@@ -440,22 +590,19 @@ namespace boost {
|
||||
pointer_const_type get_ptr() const { return is_initialized() ? dataptr() : nullptr; }
|
||||
pointer_type get_ptr() { return is_initialized() ? dataptr() : nullptr; }
|
||||
|
||||
constexpr reference_const_type operator*() const& { return this->get(); }
|
||||
constexpr reference_type operator*() & { return this->get(); }
|
||||
constexpr reference_type_of_temporary_wrapper operator*() && { return optional_detail::move_(this->get()); }
|
||||
constexpr reference_const_type operator*() const& { return this->get(); }
|
||||
BOOST_CXX14_CONSTEXPR reference_type operator*() & { return this->get(); }
|
||||
BOOST_CXX14_CONSTEXPR reference_type_of_temporary_wrapper operator*() && { return optional_detail::move_(this->get()); }
|
||||
|
||||
constexpr pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->dataptr(); }
|
||||
constexpr pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->dataptr(); }
|
||||
constexpr pointer_const_type operator->() const { return BOOST_OPTIONAL_ASSERTED_EXPRESSION(this->is_initialized(), this->dataptr()); }
|
||||
BOOST_CXX14_CONSTEXPR pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->dataptr(); }
|
||||
|
||||
constexpr reference_const_type value() const&
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return this->get();
|
||||
else
|
||||
boost::throw_exception(boost::bad_optional_access());
|
||||
return this->is_initialized() ? this->get() : (boost::throw_exception(boost::bad_optional_access()), this->get());
|
||||
}
|
||||
|
||||
constexpr reference_type value() &
|
||||
BOOST_CXX14_CONSTEXPR reference_type value() &
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return this->get();
|
||||
@@ -463,7 +610,7 @@ namespace boost {
|
||||
boost::throw_exception(boost::bad_optional_access());
|
||||
}
|
||||
|
||||
constexpr reference_type_of_temporary_wrapper value() &&
|
||||
BOOST_CXX14_CONSTEXPR reference_type_of_temporary_wrapper value() &&
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return optional_detail::move_(this->get());
|
||||
@@ -471,17 +618,15 @@ namespace boost {
|
||||
boost::throw_exception(boost::bad_optional_access());
|
||||
}
|
||||
|
||||
template <class U = T>
|
||||
template <class U = typename ::std::remove_cv<T>::type,
|
||||
typename fail_hard_on_nonconvertible<T, U>::type = true>
|
||||
constexpr value_type value_or(U&& v) const&
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return get();
|
||||
else
|
||||
return optional_detail::forward_<U>(v);
|
||||
return this->is_initialized() ? get() : T(optional_detail::forward_<U>(v));
|
||||
}
|
||||
|
||||
template <class U>
|
||||
constexpr value_type value_or(U&& v) &&
|
||||
template <class U = typename ::std::remove_cv<T>::type>
|
||||
BOOST_CXX14_CONSTEXPR value_type value_or(U&& v) &&
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return optional_detail::move_(get());
|
||||
@@ -489,17 +634,15 @@ namespace boost {
|
||||
return optional_detail::forward_<U>(v);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
template <typename F,
|
||||
typename fail_hard_on_nonconvertible<T, decltype(optional_detail::declval_<F>()())>::type = true>
|
||||
constexpr value_type value_or_eval(F f) const&
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return get();
|
||||
else
|
||||
return f();
|
||||
return this->is_initialized() ? get() : value_type(f());
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
constexpr value_type value_or_eval ( F f ) &&
|
||||
BOOST_CXX14_CONSTEXPR value_type value_or_eval ( F f ) &&
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return optional_detail::move_(get());
|
||||
@@ -508,7 +651,8 @@ namespace boost {
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
constexpr optional<typename optional_detail::result_of<F, reference_type>::type> map(F f) &
|
||||
BOOST_CXX14_CONSTEXPR optional<typename optional_detail::result_of<F, reference_type>::type>
|
||||
map(F f) &
|
||||
{
|
||||
if (this->has_value())
|
||||
return f(get());
|
||||
@@ -517,16 +661,17 @@ namespace boost {
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
constexpr optional<typename optional_detail::result_of<F, reference_const_type>::type> map(F f) const&
|
||||
constexpr optional<typename optional_detail::result_of<F, reference_const_type>::type>
|
||||
map(F f) const&
|
||||
{
|
||||
if (this->has_value())
|
||||
return f(get());
|
||||
else
|
||||
return none;
|
||||
return this->has_value() ?
|
||||
f(get()) :
|
||||
optional<typename optional_detail::result_of<F, reference_const_type>::type>();
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
constexpr optional<typename optional_detail::result_of<F, reference_type_of_temporary_wrapper>::type> map(F f) &&
|
||||
BOOST_CXX14_CONSTEXPR optional<typename optional_detail::result_of<F, reference_type_of_temporary_wrapper>::type>
|
||||
map(F f) &&
|
||||
{
|
||||
if (this->has_value())
|
||||
return f(optional_detail::move_(this->get()));
|
||||
@@ -535,7 +680,7 @@ namespace boost {
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
constexpr optional<typename optional_detail::result_value_type<F, reference_type>::type>
|
||||
BOOST_CXX14_CONSTEXPR optional<typename optional_detail::result_value_type<F, reference_type>::type>
|
||||
flat_map(F f) &
|
||||
{
|
||||
if (this->has_value())
|
||||
@@ -548,14 +693,13 @@ namespace boost {
|
||||
constexpr optional<typename optional_detail::result_value_type<F, reference_const_type>::type>
|
||||
flat_map(F f) const&
|
||||
{
|
||||
if (this->has_value())
|
||||
return f(get());
|
||||
else
|
||||
return none;
|
||||
return this->has_value() ?
|
||||
f(get()) :
|
||||
optional<typename optional_detail::result_value_type<F, reference_const_type>::type>();
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
constexpr optional<typename optional_detail::result_value_type<F, reference_type_of_temporary_wrapper>::type>
|
||||
BOOST_CXX14_CONSTEXPR optional<typename optional_detail::result_value_type<F, reference_type_of_temporary_wrapper>::type>
|
||||
flat_map(F f) &&
|
||||
{
|
||||
if (this->has_value())
|
||||
@@ -577,6 +721,4 @@ namespace boost {
|
||||
}
|
||||
|
||||
|
||||
// https://godbolt.org/z/ov1ahMsv6
|
||||
|
||||
#endif // BOOST_OPTIONAL_DETAIL_CONSTEXPR_OPTIONAL_01FEB2026_HPP
|
||||
#endif // BOOST_OPTIONAL_DETAIL_UNION_OPTIONAL_01FEB2026_HPP
|
||||
@@ -23,15 +23,7 @@
|
||||
#define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
|
||||
|
||||
|
||||
#if !defined(BOOST_NO_CXX14_CONSTEXPR) && \
|
||||
!defined(BOOST_NO_CXX11_REF_QUALIFIERS) && \
|
||||
!defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \
|
||||
!defined(BOOST_NO_CXX11_UNRESTRICTED_UNION)
|
||||
# ifdef BOOST_OPTIONAL_CONFIG_ENABLE_CONSTEXPR_IMPLEMENTATION // for now, only per manual request
|
||||
# define BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/optional/detail/optional_select_implementation.hpp>
|
||||
#include <boost/optional/detail/optional_common_defs.hpp>
|
||||
|
||||
|
||||
@@ -56,8 +48,8 @@ operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optiona
|
||||
#include <boost/none.hpp>
|
||||
|
||||
|
||||
#if defined BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
#include <boost/optional/detail/constexpr_optional.hpp>
|
||||
#if defined BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
#include <boost/optional/detail/union_optional.hpp>
|
||||
#else
|
||||
|
||||
|
||||
@@ -92,10 +84,8 @@ operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optiona
|
||||
#include <boost/type_traits/is_volatile.hpp>
|
||||
#include <boost/type_traits/is_scalar.hpp>
|
||||
|
||||
|
||||
#include <boost/optional/optional_fwd.hpp>
|
||||
#include <boost/optional/detail/optional_config.hpp>
|
||||
#include <boost/optional/detail/optional_factory_support.hpp>
|
||||
#include <boost/optional/detail/optional_aligned_storage.hpp>
|
||||
|
||||
|
||||
|
||||
@@ -17,25 +17,32 @@
|
||||
#define BOOST_OPTIONAL_OPTIONAL_FWD_FLC_19NOV2002_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/invoke_swap.hpp>
|
||||
#include <boost/optional/detail/optional_select_implementation.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<class T> class optional ;
|
||||
|
||||
// This forward is needed to refer to namespace scope swap from the member swap
|
||||
#ifdef BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
template<class T> BOOST_OPTIONAL_CXX20_CONSTEXPR void swap ( optional<T>& , optional<T>& ) ;
|
||||
#ifdef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
template<class T> BOOST_OPTIONAL_CXX20_CONSTEXPR void swap ( optional<T>& lhs, optional<T>& rhs )
|
||||
noexcept(::std::is_nothrow_move_constructible<T>::value && noexcept(boost::core::invoke_swap(*lhs, *rhs)));
|
||||
#else
|
||||
template<class T> void swap ( optional<T>& , optional<T>& ) ;
|
||||
#endif // BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
template<class T> void swap ( optional<T>& , optional<T>& ) ;
|
||||
#endif // BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
|
||||
|
||||
template<class T> struct optional_swap_should_use_default_constructor ;
|
||||
|
||||
|
||||
#ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS
|
||||
|
||||
template<class T> class optional<T&> ;
|
||||
template<class T> class optional<T&> ;
|
||||
|
||||
template<class T> BOOST_CXX14_CONSTEXPR void swap ( optional<T&>& , optional<T&>& ) BOOST_NOEXCEPT;
|
||||
template<class T> BOOST_CXX14_CONSTEXPR void swap ( optional<T&>& , optional<T&>& ) BOOST_NOEXCEPT;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+4
-1
@@ -28,7 +28,6 @@ project
|
||||
cxx11_explicit_conversion_operators
|
||||
# cxx11_noexcept
|
||||
cxx11_rvalue_references
|
||||
cxx11_static_assert
|
||||
cxx11_variadic_templates
|
||||
]
|
||||
;
|
||||
@@ -39,7 +38,9 @@ run optional_test_assign.cpp ;
|
||||
run optional_test_swap.cpp ;
|
||||
compile optional_test_constexpr.cpp ;
|
||||
compile optional_test_wuninitialized.cpp ;
|
||||
compile optional_test_fwd_header.cpp ;
|
||||
run optional_test_conversions_from_U.cpp ;
|
||||
run optional_test_constructors.cpp ;
|
||||
run optional_test_convert_from_T.cpp ;
|
||||
run optional_test_convert_assign.cpp ;
|
||||
run optional_test_empty_braces.cpp ;
|
||||
@@ -48,6 +49,7 @@ run optional_test_flat_map.cpp ;
|
||||
run optional_test_hash.cpp ;
|
||||
run optional_test_map.cpp ;
|
||||
run optional_test_tie.cpp : : : <library>/boost/tuple//boost_tuple ;
|
||||
run optional_test_ranges_find.cpp ;
|
||||
run optional_test_ref_assign_portable_minimum.cpp ;
|
||||
run optional_test_ref_assign_mutable_int.cpp ;
|
||||
run optional_test_ref_assign_const_int.cpp ;
|
||||
@@ -79,6 +81,7 @@ compile-fail optional_test_fail3b.cpp ;
|
||||
compile-fail optional_test_ref_fail1.cpp ;
|
||||
compile-fail optional_test_ref_fail3.cpp ;
|
||||
compile-fail optional_test_ref_fail4.cpp ;
|
||||
compile-fail optional_test_ref_fail_convert_from_temporary_optional_T.cpp ;
|
||||
compile-fail optional_test_inplace_fail.cpp ;
|
||||
compile-fail optional_test_inplace_fail2.cpp ;
|
||||
compile-fail optional_test_fail_implicit_bool_convert.cpp ;
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright (C) 2021 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
template <typename U>
|
||||
struct wrapper {};
|
||||
|
||||
template <typename /*Tag*/, typename U>
|
||||
int get(wrapper<U> const&) { return 0; }
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
namespace boost
|
||||
{
|
||||
struct any_type_in_boost_namespace {};
|
||||
}
|
||||
|
||||
class tag; // user-defined tag
|
||||
|
||||
int main()
|
||||
{
|
||||
// the following tests if boost::get for optional<> does
|
||||
// not interfere with the global get
|
||||
return get<tag>(wrapper<boost::any_type_in_boost_namespace>());
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
#ifdef BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
#ifdef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
|
||||
struct Record
|
||||
{
|
||||
@@ -20,43 +20,55 @@ struct Record
|
||||
constexpr int operator()() const { return i; }
|
||||
};
|
||||
|
||||
struct Guard
|
||||
{
|
||||
int i;
|
||||
constexpr explicit Guard(int i) : i(i) {}
|
||||
Guard(Guard&&) = delete;
|
||||
};
|
||||
|
||||
static_assert(boost::none == boost::none, "");
|
||||
static_assert(!(boost::none != boost::none), "");
|
||||
|
||||
namespace test_int
|
||||
{
|
||||
constexpr boost::optional<int> oN;
|
||||
static_assert(!oN);
|
||||
static_assert(oN == boost::none);
|
||||
static_assert(oN <= boost::none);
|
||||
static_assert(!(oN != boost::none));
|
||||
static_assert(oN == oN);
|
||||
static_assert(!oN.has_value());
|
||||
static_assert(oN.value_or({}) == 0);
|
||||
static_assert(oN.value_or(0) == 0);
|
||||
static_assert(oN.value_or_eval(Record(9)) == 9);
|
||||
static_assert(!oN, "");
|
||||
static_assert(oN == boost::none, "");
|
||||
static_assert(oN <= boost::none, "");
|
||||
static_assert(!(oN != boost::none), "");
|
||||
static_assert(oN == oN, "");
|
||||
static_assert(!oN.has_value(), "");
|
||||
static_assert(oN.value_or({}) == 0, "");
|
||||
static_assert(oN.value_or(0) == 0, "");
|
||||
static_assert(oN.value_or_eval(Record(9)) == 9, "");
|
||||
|
||||
constexpr boost::optional<int> o1 (1);
|
||||
constexpr boost::optional<int> o2 {2};
|
||||
|
||||
static_assert(o1, "");
|
||||
static_assert(o1.has_value(), "");
|
||||
static_assert(o1 != boost::none, "");
|
||||
static_assert(o1 != oN, "");
|
||||
static_assert(o1 > oN, "");
|
||||
static_assert(o1 >= oN, "");
|
||||
static_assert(*o1 == 1, "");
|
||||
static_assert(o1.value() == 1, "");
|
||||
static_assert(o1.value_or(0) == 1, "");
|
||||
static_assert(o1.value_or({}) == 1, "");
|
||||
static_assert(o1.value_or_eval(Record(9)) == 1, "");
|
||||
static_assert(o1 == 1, "");
|
||||
static_assert(o2, "");
|
||||
static_assert(o2 != o1, "");
|
||||
static_assert(o2 > o1, "");
|
||||
|
||||
#ifdef BOOST_OPTIONAL_CONSTEXPR_COPY
|
||||
constexpr boost::optional<int> oNc = oN;
|
||||
constexpr boost::optional<int> oNd = boost::none;
|
||||
constexpr boost::optional<int> oNe = {};
|
||||
static_assert(oNc == oN);
|
||||
static_assert(oNd == oN);
|
||||
static_assert(oNe == oN);
|
||||
|
||||
constexpr boost::optional<int> o1 = 1;
|
||||
constexpr boost::optional<int> o2 {2};
|
||||
|
||||
static_assert(o1);
|
||||
static_assert(o1.has_value());
|
||||
static_assert(o1 != boost::none);
|
||||
static_assert(o1 != oN);
|
||||
static_assert(o1 > oN);
|
||||
static_assert(o1 >= oN);
|
||||
static_assert(*o1 == 1);
|
||||
static_assert(o1.value() == 1);
|
||||
static_assert(o1.value_or(0) == 1);
|
||||
static_assert(o1.value_or({}) == 1);
|
||||
static_assert(o1.value_or_eval(Record(9)) == 1);
|
||||
static_assert(o1 == 1);
|
||||
static_assert(o2);
|
||||
static_assert(o2 != o1);
|
||||
static_assert(o2 > o1);
|
||||
static_assert(oNc == oN, "");
|
||||
static_assert(oNd == oN, "");
|
||||
static_assert(oNe == oN, "");
|
||||
|
||||
constexpr bool test_reset() {
|
||||
boost::optional<int> o = 1;
|
||||
@@ -66,31 +78,55 @@ namespace test_int
|
||||
return o == boost::none;
|
||||
}
|
||||
|
||||
static_assert(test_reset());
|
||||
static_assert(test_reset(), "");
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace test_record
|
||||
{
|
||||
constexpr boost::optional<Record> rN = boost::none;
|
||||
constexpr boost::optional<Record> r1 = Record(1);
|
||||
constexpr boost::optional<Record> rN (boost::none);
|
||||
constexpr boost::optional<Record> r1 (Record(1));
|
||||
constexpr boost::optional<Record> r2 (boost::in_place_init, 2);
|
||||
|
||||
static_assert(!rN);
|
||||
static_assert(rN == boost::none);
|
||||
static_assert(r1);
|
||||
static_assert(r1 != boost::none);
|
||||
static_assert(r2);
|
||||
static_assert(rN.value_or(Record(9)).i == 9);
|
||||
static_assert(r1->i == 1);
|
||||
static_assert(r2.value().i == 2);
|
||||
static_assert(!rN, "");
|
||||
static_assert(rN == boost::none, "");
|
||||
static_assert(r1, "");
|
||||
static_assert(r1 != boost::none, "");
|
||||
static_assert(r2, "");
|
||||
static_assert(rN.value_or(Record(9)).i == 9, "");
|
||||
static_assert(r1->i == 1, "");
|
||||
static_assert(r2.value().i == 2, "");
|
||||
}
|
||||
|
||||
namespace test_guard
|
||||
{
|
||||
constexpr boost::optional<Guard> g1 {boost::in_place_init, 1};
|
||||
constexpr boost::optional<Guard> gNa {boost::none};
|
||||
constexpr boost::optional<Guard> gNb;
|
||||
|
||||
static_assert(g1, "");
|
||||
static_assert(!!g1, "");
|
||||
static_assert(g1 != boost::none, "");
|
||||
static_assert(!(g1 == boost::none), "");
|
||||
static_assert(g1.has_value(), "");
|
||||
|
||||
static_assert(!gNa, "");
|
||||
static_assert(!gNa.has_value(), "");
|
||||
static_assert(gNa == boost::none, "");
|
||||
static_assert(!(gNa != boost::none), "");
|
||||
|
||||
static_assert(!gNb, "");
|
||||
static_assert(!gNb.has_value(), "");
|
||||
static_assert(gNb == boost::none, "");
|
||||
static_assert(!(gNb != boost::none), "");
|
||||
}
|
||||
|
||||
namespace test_optional_ref
|
||||
{
|
||||
constexpr int gi = 9;
|
||||
constexpr boost::optional<const int&> iref = gi;
|
||||
static_assert(iref);
|
||||
static_assert(*iref == 9);
|
||||
static_assert(iref, "");
|
||||
static_assert(*iref == 9, "");
|
||||
}
|
||||
|
||||
#endif // BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
#endif // BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
|
||||
@@ -55,5 +55,6 @@ int main()
|
||||
{
|
||||
// Invokes boost::optional copy constructor. Should not invoke wrapper constructor from U.
|
||||
boost::optional< wrapper< int > > res = foo();
|
||||
(void)res;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
// Copyright (C) 2026 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include <string>
|
||||
|
||||
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
|
||||
struct MyBool
|
||||
{
|
||||
bool b;
|
||||
MyBool (bool b) : b(b) {}
|
||||
operator bool() const { return b; };
|
||||
};
|
||||
|
||||
struct MyExplicitBool
|
||||
{
|
||||
bool b;
|
||||
MyExplicitBool (bool b) : b(b) {}
|
||||
operator bool() const { return b; };
|
||||
};
|
||||
|
||||
struct Any
|
||||
{
|
||||
template <typename... T>
|
||||
Any(T&&...) {}
|
||||
};
|
||||
|
||||
struct JustCopyMoveCtor
|
||||
{
|
||||
JustCopyMoveCtor(JustCopyMoveCtor&&) = default;
|
||||
JustCopyMoveCtor(JustCopyMoveCtor const&) = default;
|
||||
JustCopyMoveCtor& operator=(JustCopyMoveCtor&&) = delete;
|
||||
JustCopyMoveCtor& operator=(JustCopyMoveCtor const&) = delete;
|
||||
JustCopyMoveCtor() = delete;
|
||||
};
|
||||
|
||||
struct JustDefault
|
||||
{
|
||||
JustDefault() = default;
|
||||
JustDefault(JustDefault&&) = delete;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
optional<T> empty_optional()
|
||||
{
|
||||
return optional<T>(); // this is to avoid "the most vexing parse"
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename U>
|
||||
void direct_test_ctor_optional_T_from_empty_optional_T()
|
||||
{
|
||||
optional<U> om;
|
||||
const optional<U> oc;
|
||||
BOOST_TEST(!om);
|
||||
BOOST_TEST(!oc);
|
||||
|
||||
{
|
||||
optional<T> ox = om;
|
||||
BOOST_TEST(!ox);
|
||||
|
||||
optional<T> oy = oc;
|
||||
BOOST_TEST(!oy);
|
||||
|
||||
optional<T> oz = empty_optional<U>();
|
||||
BOOST_TEST(!oz);
|
||||
}
|
||||
|
||||
{
|
||||
optional<T> ox = {om};
|
||||
BOOST_TEST(!ox);
|
||||
|
||||
optional<T> oy = {oc};
|
||||
BOOST_TEST(!oy);
|
||||
|
||||
optional<T> oz = {empty_optional<U>()};
|
||||
BOOST_TEST(!oz);
|
||||
}
|
||||
|
||||
{
|
||||
optional<T> ox{om};
|
||||
BOOST_TEST(!ox);
|
||||
|
||||
optional<T> oy{oc};
|
||||
BOOST_TEST(!oy);
|
||||
|
||||
optional<T> oz{empty_optional<U>()};
|
||||
BOOST_TEST(!oz);
|
||||
}
|
||||
|
||||
{
|
||||
optional<T> ox(om);
|
||||
BOOST_TEST(!ox);
|
||||
|
||||
optional<T> oy(oc);
|
||||
BOOST_TEST(!oy);
|
||||
|
||||
optional<T> oz(empty_optional<U>());
|
||||
BOOST_TEST(!oz);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void test_ctor_optional_T_from_empty_optional_T()
|
||||
{
|
||||
direct_test_ctor_optional_T_from_empty_optional_T<T, U>();
|
||||
direct_test_ctor_optional_T_from_empty_optional_T<const T, const U>();
|
||||
direct_test_ctor_optional_T_from_empty_optional_T<optional<T>, optional<U>>();
|
||||
direct_test_ctor_optional_T_from_empty_optional_T<optional<const T>, optional<const U>>();
|
||||
direct_test_ctor_optional_T_from_empty_optional_T<const optional<T>, const optional<U>>();
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void direct_test_ctor_optional_T_from_optional_U(U val)
|
||||
{
|
||||
optional<U> om;
|
||||
const optional<U> oc;
|
||||
BOOST_TEST(!om);
|
||||
BOOST_TEST(!oc);
|
||||
|
||||
{
|
||||
optional<T> ox{om};
|
||||
BOOST_TEST(!ox);
|
||||
|
||||
optional<T> oy{oc};
|
||||
BOOST_TEST(!oy);
|
||||
|
||||
optional<T> oz{empty_optional<U>()};
|
||||
BOOST_TEST(!oz);
|
||||
}
|
||||
|
||||
{
|
||||
optional<T> ox(om);
|
||||
BOOST_TEST(!ox);
|
||||
|
||||
optional<T> oy(oc);
|
||||
BOOST_TEST(!oy);
|
||||
|
||||
optional<T> oz(empty_optional<U>());
|
||||
BOOST_TEST(!oz);
|
||||
}
|
||||
|
||||
{
|
||||
optional<U> om {val};
|
||||
const optional<U> oc {val};
|
||||
|
||||
{
|
||||
optional<T> ox{om};
|
||||
BOOST_TEST(ox);
|
||||
|
||||
optional<T> oy{oc};
|
||||
BOOST_TEST(oy);
|
||||
|
||||
optional<T> oz{boost::make_optional(val)};
|
||||
BOOST_TEST(oz);
|
||||
}
|
||||
{
|
||||
optional<T> ox(om);
|
||||
BOOST_TEST(ox);
|
||||
|
||||
optional<T> oy(oc);
|
||||
BOOST_TEST(oy);
|
||||
|
||||
optional<T> oz(boost::make_optional(val));
|
||||
BOOST_TEST(oz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void test_ctor_optional_T_from_optional_U(U val)
|
||||
{
|
||||
direct_test_ctor_optional_T_from_optional_U<T>(val);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void direct_test_ctor_optional_T_from_valued_optional_T(T val)
|
||||
{
|
||||
optional<T> om(val);
|
||||
const optional<T> oc(val);
|
||||
BOOST_TEST(om);
|
||||
BOOST_TEST(oc);
|
||||
|
||||
{
|
||||
optional<T> ox = om;
|
||||
BOOST_TEST(ox);
|
||||
|
||||
optional<T> oy = oc;
|
||||
BOOST_TEST(oy);
|
||||
|
||||
optional<T> oz = optional<T>(val);
|
||||
BOOST_TEST(oz);
|
||||
}
|
||||
{
|
||||
optional<T> ox = {om};
|
||||
BOOST_TEST(ox);
|
||||
|
||||
optional<T> oy = {oc};
|
||||
BOOST_TEST(oy);
|
||||
|
||||
optional<T> oz = {optional<T>(val)};
|
||||
BOOST_TEST(oz);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_ctor_optional_T_from_valued_optional_T(T val)
|
||||
{
|
||||
direct_test_ctor_optional_T_from_valued_optional_T<T>(val);
|
||||
direct_test_ctor_optional_T_from_valued_optional_T<optional<T>>(val);
|
||||
direct_test_ctor_optional_T_from_valued_optional_T<const T>(val);
|
||||
direct_test_ctor_optional_T_from_optional_U<T, T>(val);
|
||||
direct_test_ctor_optional_T_from_optional_U<optional<T>, optional<T>>(val);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void direct_test_inplace_tag_constructor()
|
||||
{
|
||||
{
|
||||
optional<T> ox (boost::in_place_init);
|
||||
BOOST_TEST(ox);
|
||||
}
|
||||
{
|
||||
optional<T> ox {boost::in_place_init};
|
||||
BOOST_TEST(ox);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_inplace_tag_constructor()
|
||||
{
|
||||
direct_test_inplace_tag_constructor<T>();
|
||||
direct_test_inplace_tag_constructor<optional<T>>();
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test_ctor_optional_T_from_empty_optional_T<int, int>();
|
||||
test_ctor_optional_T_from_empty_optional_T<long, long>();
|
||||
test_ctor_optional_T_from_empty_optional_T<std::string, std::string>();
|
||||
test_ctor_optional_T_from_empty_optional_T<JustCopyMoveCtor, JustCopyMoveCtor>();
|
||||
test_ctor_optional_T_from_empty_optional_T<MyBool, MyBool>();
|
||||
|
||||
test_ctor_optional_T_from_empty_optional_T<MyExplicitBool, MyExplicitBool>();
|
||||
|
||||
test_ctor_optional_T_from_empty_optional_T<bool, bool>();
|
||||
test_ctor_optional_T_from_empty_optional_T<Any, Any>();
|
||||
|
||||
test_inplace_tag_constructor<int>();
|
||||
test_inplace_tag_constructor<Any>();
|
||||
test_inplace_tag_constructor<JustDefault>();
|
||||
|
||||
test_ctor_optional_T_from_optional_U<int>(1);
|
||||
test_ctor_optional_T_from_optional_U<long>(1);
|
||||
test_ctor_optional_T_from_optional_U<bool>(MyBool{true});
|
||||
test_ctor_optional_T_from_optional_U<bool>(MyBool{false});
|
||||
test_ctor_optional_T_from_optional_U<MyBool>(true);
|
||||
test_ctor_optional_T_from_optional_U<MyBool>(false);
|
||||
test_ctor_optional_T_from_optional_U<bool>(MyExplicitBool{true});
|
||||
test_ctor_optional_T_from_optional_U<bool>(MyExplicitBool{false});
|
||||
test_ctor_optional_T_from_optional_U<MyExplicitBool>(true);
|
||||
test_ctor_optional_T_from_optional_U<MyExplicitBool>(false);
|
||||
test_ctor_optional_T_from_optional_U<Any>(true);
|
||||
test_ctor_optional_T_from_optional_U<Any>(Any{});
|
||||
|
||||
test_ctor_optional_T_from_valued_optional_T(1);
|
||||
|
||||
optional<MyBool> ob;
|
||||
optional<bool> oa;
|
||||
oa = ob;
|
||||
BOOST_TEST(!oa);
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -45,6 +45,8 @@ void test_optional_of_superconverting_T() // compile-time test
|
||||
superconv<optional<int> > s;
|
||||
superconv<optional<int> > & rs = s;
|
||||
optional<superconv<optional<int> > > os = rs;
|
||||
(void)s;
|
||||
(void)os;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -29,4 +29,3 @@ void test_implicit_conversion_to_bool()
|
||||
boost::optional<T> opt;
|
||||
opt.value_or(U());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright (C) 2026 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional/optional_fwd.hpp"
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
void statically_test_basic_instantiations()
|
||||
{
|
||||
boost::optional<int> oN, o1(1);
|
||||
swap(oN, o1);
|
||||
|
||||
int i = 1;
|
||||
boost::optional<int> rN, ri(i);
|
||||
swap(rN, ri);
|
||||
}
|
||||
@@ -105,9 +105,42 @@ void test_assign()
|
||||
#endif
|
||||
}
|
||||
|
||||
// begin Boost.Log case
|
||||
|
||||
template <typename CharT>
|
||||
struct basic_formatter
|
||||
{
|
||||
template< typename FunT >
|
||||
basic_formatter(FunT&&) {}
|
||||
|
||||
template< typename FunT >
|
||||
basic_formatter& operator= (FunT&&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename CharT>
|
||||
struct chained_formatter
|
||||
{
|
||||
};
|
||||
|
||||
void test_boost_log_case()
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
|
||||
boost::optional<basic_formatter<char>> of( boost::in_place(chained_formatter<char>()) );
|
||||
of = boost::in_place(chained_formatter<char>());
|
||||
|
||||
#endif //BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
}
|
||||
|
||||
// end Boost.Log case
|
||||
|
||||
int main()
|
||||
{
|
||||
test_ctor();
|
||||
test_assign();
|
||||
test_boost_log_case();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ void test()
|
||||
//BOOST_TEST(v);
|
||||
boost::optional<boost::optional<int>> vv;
|
||||
bool xx = vv?true : false;
|
||||
(void)xx;
|
||||
BOOST_TEST_EQ(*v, 7);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2026 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include <type_traits>
|
||||
|
||||
#ifndef BOOST_NO_CXX20_HDR_RANGES
|
||||
#include <ranges>
|
||||
#include <concepts>
|
||||
#include <iterator>
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
static_assert(std::equality_comparable<boost::none_t>, "boost::none shall be equality comparable");
|
||||
|
||||
|
||||
template <typename T>
|
||||
void test_that_you_can_find_none_in_a_range_of_optional(T x, T y)
|
||||
{
|
||||
static_assert(std::equality_comparable_with<boost::optional<T>, boost::none_t>, "boost::none shall satisfy the concept");
|
||||
static_assert(std::equality_comparable_with<boost::none_t, boost::optional<T> >, "boost::none shall satisfy the concept");
|
||||
static_assert(std::indirect_binary_predicate<std::ranges::equal_to, const boost::optional<T>*, const boost::none_t*>, "boost::none shall satisfy the concept");
|
||||
|
||||
// [0] [1] [2]
|
||||
std::array<boost::optional<T>, 3> arr = {{ x, boost::none, y }};
|
||||
auto it = std::ranges::find(arr, boost::none);
|
||||
BOOST_TEST_EQ(std::distance(arr.begin(), it), 1);
|
||||
}
|
||||
#endif // BOOST_NO_CXX20_HDR_RANGES
|
||||
|
||||
|
||||
# if (defined __GNUC__) && (!defined BOOST_INTEL_CXX_VERSION) && (!defined __clang__)
|
||||
# if (__GNUC__ <= 4)
|
||||
# define BOOST_OPTIONAL_TEST_INSUFFICIENT_TYPE_TRAIT_SUPPORT
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#ifndef BOOST_OPTIONAL_TEST_INSUFFICIENT_TYPE_TRAIT_SUPPORT
|
||||
static_assert(std::is_trivially_copyable<boost::none_t>::value, "boost::none shall be trivially copyable");
|
||||
#endif
|
||||
|
||||
|
||||
void test_that_none_is_equal_to_none()
|
||||
{
|
||||
BOOST_TEST(boost::none == boost::none);
|
||||
BOOST_TEST(!(boost::none != boost::none));
|
||||
auto None = boost::none;
|
||||
BOOST_TEST(None == boost::none);
|
||||
BOOST_TEST(!(None != boost::none));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef BOOST_NO_CXX20_HDR_RANGES
|
||||
test_that_you_can_find_none_in_a_range_of_optional(1, 2);
|
||||
test_that_you_can_find_none_in_a_range_of_optional<std::string>("one", "two");
|
||||
#endif
|
||||
test_that_none_is_equal_to_none();
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
void optional_reference__test_no_converting_initialization()
|
||||
{
|
||||
boost::optional<const int&> o (boost::optional<int>(1));
|
||||
(void)o;
|
||||
}
|
||||
@@ -24,7 +24,13 @@ using boost::none;
|
||||
struct Value
|
||||
{
|
||||
int val;
|
||||
explicit Value(int v) : val(v) {}
|
||||
BOOST_CONSTEXPR explicit Value(int v) : val(v) {}
|
||||
};
|
||||
|
||||
struct Guard
|
||||
{
|
||||
int val;
|
||||
BOOST_CONSTEXPR explicit Guard(int v) : val(v) {}
|
||||
};
|
||||
|
||||
int val(int const& i)
|
||||
@@ -37,6 +43,11 @@ int val(Value const& v)
|
||||
return v.val;
|
||||
}
|
||||
|
||||
int val(Guard const& v)
|
||||
{
|
||||
return v.val;
|
||||
}
|
||||
|
||||
template <typename Tref>
|
||||
optional<Tref&> make_opt_ref(Tref& v)
|
||||
{
|
||||
@@ -47,21 +58,21 @@ template <typename Tval, typename Tref>
|
||||
void test_construct_from_optional_ref()
|
||||
{
|
||||
Tref v1 (1), v2 (2);
|
||||
|
||||
|
||||
optional<Tref&> opt_ref0;
|
||||
optional<Tref&> opt_ref1 (v1);
|
||||
|
||||
|
||||
optional<Tval> opt_val0 (opt_ref0);
|
||||
optional<Tval> opt_val1 (opt_ref1);
|
||||
optional<Tval> opt_val2 (make_opt_ref(v2));
|
||||
|
||||
|
||||
BOOST_TEST (!opt_val0);
|
||||
BOOST_TEST (opt_val1);
|
||||
BOOST_TEST (opt_val2);
|
||||
|
||||
|
||||
BOOST_TEST_EQ (1, val(*opt_val1));
|
||||
BOOST_TEST_EQ (2, val(*opt_val2));
|
||||
|
||||
|
||||
BOOST_TEST (boost::addressof(*opt_val1) != boost::addressof(v1));
|
||||
BOOST_TEST (boost::addressof(*opt_val2) != boost::addressof(v2));
|
||||
}
|
||||
@@ -70,29 +81,121 @@ template <typename Tval, typename Tref>
|
||||
void test_assign_from_optional_ref()
|
||||
{
|
||||
Tref v1 (1), v2 (2);
|
||||
|
||||
|
||||
optional<Tref&> opt_ref0;
|
||||
optional<Tref&> opt_ref1 (v1);
|
||||
|
||||
|
||||
optional<Tval> opt_val0;
|
||||
optional<Tval> opt_val1;
|
||||
optional<Tval> opt_val2;
|
||||
|
||||
|
||||
opt_val0 = opt_ref0;
|
||||
opt_val1 = opt_ref1;
|
||||
opt_val2 = make_opt_ref(v2);
|
||||
|
||||
|
||||
BOOST_TEST (!opt_val0);
|
||||
BOOST_TEST (opt_val1);
|
||||
BOOST_TEST (opt_val2);
|
||||
|
||||
|
||||
BOOST_TEST_EQ (1, val(*opt_val1));
|
||||
BOOST_TEST_EQ (2, val(*opt_val2));
|
||||
|
||||
|
||||
BOOST_TEST (boost::addressof(*opt_val1) != boost::addressof(v1));
|
||||
BOOST_TEST (boost::addressof(*opt_val2) != boost::addressof(v2));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_convert_optional_T_to_optional_T_ref()
|
||||
{
|
||||
#ifdef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
using boost::optional;
|
||||
using boost::in_place_init;
|
||||
|
||||
{ // optional<T>& -> optional<T&>
|
||||
optional<T> ovN, ov1(in_place_init, 1), ov2(in_place_init, 2);
|
||||
|
||||
optional<T&> orN = ovN;
|
||||
optional<T&> or1 = ov1;
|
||||
optional<T&> or2 = ov2;
|
||||
|
||||
BOOST_TEST_EQ (!!orN, !!ovN);
|
||||
BOOST_TEST_EQ (!!or1, !!ov1);
|
||||
BOOST_TEST_EQ (!!or2, !!ov2);
|
||||
|
||||
BOOST_TEST (or1);
|
||||
BOOST_TEST (or2);
|
||||
BOOST_TEST_EQ (val(*or1), 1);
|
||||
BOOST_TEST_EQ (val(*or2), 2);
|
||||
BOOST_TEST (boost::addressof(*or1) == boost::addressof(*ov1));
|
||||
BOOST_TEST (boost::addressof(*or2) == boost::addressof(*ov2));
|
||||
}
|
||||
|
||||
{ // const optional<T>& -> optional<const T&>
|
||||
constexpr optional<T> ovN;
|
||||
constexpr optional<T> ov1(in_place_init, 1);
|
||||
constexpr optional<T> ov2(in_place_init, 2);
|
||||
|
||||
optional<const T&> orN = ovN;
|
||||
optional<const T&> or1 = ov1;
|
||||
optional<const T&> or2 = ov2;
|
||||
|
||||
BOOST_TEST_EQ (!!orN, !!ovN);
|
||||
BOOST_TEST_EQ (!!or1, !!ov1);
|
||||
BOOST_TEST_EQ (!!or2, !!ov2);
|
||||
|
||||
BOOST_TEST (or1);
|
||||
BOOST_TEST (or2);
|
||||
BOOST_TEST_EQ (val(*or1), 1);
|
||||
BOOST_TEST_EQ (val(*or2), 2);
|
||||
BOOST_TEST (boost::addressof(*or1) == boost::addressof(*ov1));
|
||||
BOOST_TEST (boost::addressof(*or2) == boost::addressof(*ov2));
|
||||
}
|
||||
|
||||
{ // optional<const T>& -> optional<const T&>
|
||||
optional<const T> ovN;
|
||||
optional<const T> ov1(in_place_init, 1);
|
||||
optional<const T> ov2(in_place_init, 2);
|
||||
|
||||
optional<const T&> orN = ovN;
|
||||
optional<const T&> or1 = ov1;
|
||||
optional<const T&> or2 = ov2;
|
||||
|
||||
BOOST_TEST_EQ (!!orN, !!ovN);
|
||||
BOOST_TEST_EQ (!!or1, !!ov1);
|
||||
BOOST_TEST_EQ (!!or2, !!ov2);
|
||||
|
||||
BOOST_TEST (or1);
|
||||
BOOST_TEST (or2);
|
||||
BOOST_TEST_EQ (val(*or1), 1);
|
||||
BOOST_TEST_EQ (val(*or2), 2);
|
||||
BOOST_TEST (boost::addressof(*or1) == boost::addressof(*ov1));
|
||||
BOOST_TEST (boost::addressof(*or2) == boost::addressof(*ov2));
|
||||
}
|
||||
|
||||
{ // optional<T>& -> optional<const T&>
|
||||
optional<T> ovN;
|
||||
optional<T> ov1(in_place_init, 1);
|
||||
optional<T> ov2(in_place_init, 2);
|
||||
|
||||
optional<const T&> orN = ovN;
|
||||
optional<const T&> or1 = ov1;
|
||||
optional<const T&> or2 = ov2;
|
||||
|
||||
BOOST_TEST_EQ (!!orN, !!ovN);
|
||||
BOOST_TEST_EQ (!!or1, !!ov1);
|
||||
BOOST_TEST_EQ (!!or2, !!ov2);
|
||||
|
||||
BOOST_TEST (or1);
|
||||
BOOST_TEST (or2);
|
||||
BOOST_TEST_EQ (val(*or1), 1);
|
||||
BOOST_TEST_EQ (val(*or2), 2);
|
||||
BOOST_TEST (boost::addressof(*or1) == boost::addressof(*ov1));
|
||||
BOOST_TEST (boost::addressof(*or2) == boost::addressof(*ov2));
|
||||
}
|
||||
|
||||
#endif // BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -100,17 +203,21 @@ int main()
|
||||
test_construct_from_optional_ref<int, int const>();
|
||||
test_construct_from_optional_ref<int const, int const>();
|
||||
test_construct_from_optional_ref<int const, int>();
|
||||
|
||||
|
||||
test_construct_from_optional_ref<Value, Value>();
|
||||
test_construct_from_optional_ref<Value, Value const>();
|
||||
test_construct_from_optional_ref<Value const, Value const>();
|
||||
test_construct_from_optional_ref<Value const, Value>();
|
||||
|
||||
|
||||
test_assign_from_optional_ref<int, int>();
|
||||
test_assign_from_optional_ref<int, int const>();
|
||||
|
||||
test_assign_from_optional_ref<Value, Value>();
|
||||
test_assign_from_optional_ref<Value, Value const>();
|
||||
|
||||
test_convert_optional_T_to_optional_T_ref<int>();
|
||||
test_convert_optional_T_to_optional_T_ref<Value>();
|
||||
test_convert_optional_T_to_optional_T_ref<Guard>();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "boost/type_traits/is_base_of.hpp"
|
||||
#include "boost/optional/detail/experimental_traits.hpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
#ifndef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
|
||||
|
||||
struct PrivDefault
|
||||
@@ -136,11 +136,11 @@ void test_trivial_copyability()
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
#endif // BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
#ifndef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
|
||||
test_type_traits();
|
||||
test_trivial_copyability();
|
||||
|
||||
@@ -210,7 +210,7 @@ namespace boost {
|
||||
// Compile time tweaking on whether or not swap should use the default constructor:
|
||||
//
|
||||
|
||||
#ifndef BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
#ifndef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
template <> struct optional_swap_should_use_default_constructor<
|
||||
optional_swap_test::class_whose_default_ctor_should_be_used> : true_type {} ;
|
||||
|
||||
@@ -219,7 +219,7 @@ template <> struct optional_swap_should_use_default_constructor<
|
||||
|
||||
template <class T> struct optional_swap_should_use_default_constructor<
|
||||
optional_swap_test::template_whose_default_ctor_should_be_used<T> > : true_type {} ;
|
||||
#endif // BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
#endif // BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
|
||||
//
|
||||
// Specialization of boost::swap:
|
||||
@@ -353,14 +353,14 @@ void test_swap_member_function( T const* )
|
||||
void test_swap_tweaking()
|
||||
{
|
||||
( test_swap_function( ARG(optional_swap_test::class_without_default_ctor) ) );
|
||||
#ifndef BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
#ifndef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
( test_swap_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) );
|
||||
( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) );
|
||||
( test_swap_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) );
|
||||
( test_swap_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used<char>) ) );
|
||||
#endif
|
||||
( test_swap_member_function( ARG(optional_swap_test::class_without_default_ctor) ) );
|
||||
#ifndef BOOST_OPTIONAL_USES_CONSTEXPR_IMPLEMENTATION
|
||||
#ifndef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
( test_swap_member_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) );
|
||||
( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_be_used) ) );
|
||||
( test_swap_member_function( ARG(optional_swap_test::class_whose_default_ctor_should_not_be_used) ) );
|
||||
|
||||
Reference in New Issue
Block a user