mirror of
https://github.com/boostorg/optional.git
synced 2026-04-28 18:02:04 +02:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ecb241a919 | |||
| ff710d113c | |||
| 88e2378c8a | |||
| fa52755c88 | |||
| 76be15bfeb | |||
| 5d8e50a9aa | |||
| 37513ddbbf | |||
| 953b678b39 | |||
| b2057c8dfe | |||
| 1c13f5f724 | |||
| aa1cf1e76c | |||
| 938502da88 | |||
| 046357ce54 | |||
| b6a57cdb46 | |||
| dd0e9d8a72 | |||
| c81b9b098b | |||
| 7b078be18d | |||
| 3df23370e6 | |||
| bfdf0c73f9 | |||
| e1c6b5b737 | |||
| 1a8c2dcafd | |||
| 6134d0c274 |
+15
-14
@@ -10,7 +10,6 @@ on:
|
||||
|
||||
env:
|
||||
UBSAN_OPTIONS: print_stacktrace=1
|
||||
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
|
||||
|
||||
jobs:
|
||||
posix:
|
||||
@@ -69,8 +68,7 @@ jobs:
|
||||
address-model: 32,64
|
||||
- toolset: gcc-13
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
os: ubuntu-latest
|
||||
container: ubuntu:23.04
|
||||
os: ubuntu-24.04
|
||||
install: g++-13-multilib
|
||||
address-model: 32,64
|
||||
- toolset: clang
|
||||
@@ -144,37 +142,40 @@ jobs:
|
||||
- toolset: clang
|
||||
compiler: clang++-16
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
container: ubuntu:23.04
|
||||
os: ubuntu-latest
|
||||
os: ubuntu-24.04
|
||||
install: clang-16
|
||||
- toolset: clang
|
||||
compiler: clang++-17
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
container: ubuntu:23.10
|
||||
os: ubuntu-latest
|
||||
os: ubuntu-24.04
|
||||
install: clang-17
|
||||
- toolset: clang
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
os: macos-12
|
||||
- toolset: clang
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
os: macos-13
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
container: ${{matrix.container}}
|
||||
container:
|
||||
image: ${{matrix.container}}
|
||||
volumes:
|
||||
- /node20217:/node20217:rw,rshared
|
||||
- ${{ startsWith(matrix.container, 'ubuntu:1') && '/node20217:/__e/node20:ro,rshared' || ' ' }}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup container environment
|
||||
if: matrix.container
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get -y install sudo python3 git g++
|
||||
apt-get -y install sudo python3 git g++ curl
|
||||
if [[ "${{matrix.container}}" == "ubuntu:1"* ]]; then
|
||||
# Node 20 doesn't work with Ubuntu 16/18 glibc: https://github.com/actions/checkout/issues/1590
|
||||
curl -sL https://archives.boost.io/misc/node/node-v20.9.0-linux-x64-glibc-217.tar.xz | tar -xJ --strip-components 1 -C /node20217
|
||||
fi
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
|
||||
+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-2024 Andrzej Krzemieński]
|
||||
[copyright 2014-2026 Andrzej Krzemieński]
|
||||
[category miscellaneous]
|
||||
[id optional]
|
||||
[dirname optional]
|
||||
|
||||
@@ -124,7 +124,6 @@ Suppose we want to implement a ['lazy load] optimization. This is because we do
|
||||
|
||||
`optional`'s default constructor creates an uninitialized optional. No call to `Resource`'s default constructor is attempted. `Resource` doesn't have to be __STD_DEFAULT_CONSTRUCTIBLE__. In function `getResource` we first check if `resource_` is initialized. This time we do not use the contextual conversion to `bool`, but a comparison with `boost::none`. These two ways are equivalent. Function `emplace` initializes the optional in-place by perfect-forwarding the arguments to the constructor of `Resource`. No copy- or move-construction is involved here. `Resource` doesn't even have to be `MoveConstructible`.
|
||||
|
||||
[note Function `emplace` is only available on compilers that support rvalue references and variadic templates. If your compiler does not support these features and you still need to avoid any move-constructions, use [link boost_optional.design.in_place_factories In-Place Factories].]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -136,4 +136,6 @@ In-place factories can be used generically by the wrapper and user as follows:
|
||||
|
||||
The factories are implemented in the headers: __IN_PLACE_FACTORY_HPP__ and __TYPED_IN_PLACE_FACTORY_HPP__
|
||||
|
||||
[endsect]
|
||||
[caution The support for in-place factories is deprecated. Use constructor taking `in_place_init` tag and function `.emplace()` instead.]
|
||||
|
||||
[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`.
|
||||
|
||||
|
||||
@@ -95,10 +95,10 @@
|
||||
namespace boost {
|
||||
|
||||
class in_place_init_t { /* see below */ } ;
|
||||
const in_place_init_t in_place_init ( /* see below */ ) ;
|
||||
inline constexpr in_place_init_t in_place_init ( /* see below */ ) ;
|
||||
|
||||
class in_place_init_if_t { /*see below*/ } ;
|
||||
const in_place_init_if_t in_place_init_if ( /*see below*/ ) ;
|
||||
inline constexpr in_place_init_if_t in_place_init_if ( /*see below*/ ) ;
|
||||
|
||||
}
|
||||
|
||||
@@ -123,33 +123,33 @@ They are empty, trivially copyable classes with disabled default constructor.
|
||||
typedef T * pointer_type ;
|
||||
typedef T const* pointer_const_type ;
|
||||
|
||||
optional () noexcept ; ``[link reference_optional_constructor __GO_TO__]``
|
||||
constexpr optional () noexcept ; ``[link reference_optional_constructor __GO_TO__]``
|
||||
|
||||
optional ( none_t ) noexcept ; ``[link reference_optional_constructor_none_t __GO_TO__]``
|
||||
constexpr optional ( none_t ) noexcept ; ``[link reference_optional_constructor_none_t __GO_TO__]``
|
||||
|
||||
optional ( T const& v ) ; ``[link reference_optional_constructor_value __GO_TO__]``
|
||||
constexpr optional ( T const& v ) ; ``[link reference_optional_constructor_value __GO_TO__]``
|
||||
|
||||
optional ( T&& v ) ; ``[link reference_optional_constructor_move_value __GO_TO__]``
|
||||
constexpr optional ( T&& v ) ; ``[link reference_optional_constructor_move_value __GO_TO__]``
|
||||
|
||||
optional ( bool condition, T const& v ) ; ``[link reference_optional_constructor_bool_value __GO_TO__]``
|
||||
constexpr optional ( bool condition, T const& v ) ; ``[link reference_optional_constructor_bool_value __GO_TO__]``
|
||||
|
||||
optional ( optional const& rhs ) ; ``[link reference_optional_constructor_optional __GO_TO__]``
|
||||
constexpr optional ( optional const& rhs ) ; ``[link reference_optional_constructor_optional __GO_TO__]``
|
||||
|
||||
optional ( optional&& rhs ) noexcept(``['see below]``) ; ``[link reference_optional_move_constructor_optional __GO_TO__]``
|
||||
constexpr optional ( optional&& rhs ) noexcept(``['see below]``) ; ``[link reference_optional_move_constructor_optional __GO_TO__]``
|
||||
|
||||
template<class U> explicit optional ( optional<U> const& rhs ) ; ``[link reference_optional_constructor_other_optional __GO_TO__]``
|
||||
template<class U> constexpr explicit optional ( optional<U> const& rhs ) ; ``[link reference_optional_constructor_other_optional __GO_TO__]``
|
||||
|
||||
template<class U> explicit optional ( optional<U>&& rhs ) ; ``[link reference_optional_move_constructor_other_optional __GO_TO__]``
|
||||
template<class U> constexpr explicit optional ( optional<U>&& rhs ) ; ``[link reference_optional_move_constructor_other_optional __GO_TO__]``
|
||||
|
||||
template<class... Args> explicit optional ( in_place_init_t, Args&&... args ) ; ``[link reference_optional_in_place_init __GO_TO__]``
|
||||
template<class... Args> constexpr explicit optional ( in_place_init_t, Args&&... args ) ; ``[link reference_optional_in_place_init __GO_TO__]``
|
||||
|
||||
template<class... Args> explicit optional ( in_place_init_if_t, bool condition, Args&&... args ) ; ``[link reference_optional_in_place_init_if __GO_TO__]``
|
||||
template<class... Args> constexpr explicit optional ( in_place_init_if_t, bool condition, Args&&... args ) ; ``[link reference_optional_in_place_init_if __GO_TO__]``
|
||||
|
||||
template<class InPlaceFactory> explicit optional ( InPlaceFactory const& f ) ; ``[link reference_optional_constructor_factory __GO_TO__]``
|
||||
|
||||
template<class TypedInPlaceFactory> explicit optional ( TypedInPlaceFactory const& f ) ; ``[link reference_optional_constructor_factory __GO_TO__]``
|
||||
|
||||
optional& operator = ( none_t ) noexcept ; ``[link reference_optional_operator_equal_none_t __GO_TO__]``
|
||||
constexpr optional& operator = ( none_t ) noexcept ; ``[link reference_optional_operator_equal_none_t __GO_TO__]``
|
||||
|
||||
optional& operator = ( T const& v ) ; ``[link reference_optional_operator_equal_value __GO_TO__]``
|
||||
|
||||
@@ -169,44 +169,45 @@ They are empty, trivially copyable classes with disabled default constructor.
|
||||
|
||||
template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ; ``[link reference_optional_operator_equal_factory __GO_TO__]``
|
||||
|
||||
T const& get() const ; ``[link reference_optional_get __GO_TO__]``
|
||||
T& get() ; ``[link reference_optional_get __GO_TO__]``
|
||||
constexpr T const& get() const ; ``[link reference_optional_get __GO_TO__]``
|
||||
constexpr T& get() ; ``[link reference_optional_get __GO_TO__]``
|
||||
|
||||
T const* operator ->() const ; ``[link reference_optional_operator_arrow __GO_TO__]``
|
||||
T* operator ->() ; ``[link reference_optional_operator_arrow __GO_TO__]``
|
||||
constexpr T const* operator ->() const ; ``[link reference_optional_operator_arrow __GO_TO__]``
|
||||
constexpr T* operator ->() ; ``[link reference_optional_operator_arrow __GO_TO__]``
|
||||
|
||||
T const& operator *() const& ; ``[link reference_optional_operator_asterisk __GO_TO__]``
|
||||
T& operator *() & ; ``[link reference_optional_operator_asterisk __GO_TO__]``
|
||||
T&& operator *() && ; ``[link reference_optional_operator_asterisk_move __GO_TO__]``
|
||||
constexpr T const& operator *() const& ; ``[link reference_optional_operator_asterisk __GO_TO__]``
|
||||
constexpr T& operator *() & ; ``[link reference_optional_operator_asterisk __GO_TO__]``
|
||||
constexpr T&& operator *() && ; ``[link reference_optional_operator_asterisk_move __GO_TO__]``
|
||||
|
||||
T const& value() const& ; ``[link reference_optional_value __GO_TO__]``
|
||||
T& value() & ; ``[link reference_optional_value __GO_TO__]``
|
||||
T&& value() && ; ``[link reference_optional_value_move __GO_TO__]``
|
||||
constexpr T const& value() const& ; ``[link reference_optional_value __GO_TO__]``
|
||||
constexpr T& value() & ; ``[link reference_optional_value __GO_TO__]``
|
||||
constexpr T&& value() && ; ``[link reference_optional_value_move __GO_TO__]``
|
||||
|
||||
template<class U> T value_or( U && v ) const& ; ``[link reference_optional_value_or __GO_TO__]``
|
||||
template<class U> T value_or( U && v ) && ; ``[link reference_optional_value_or_move __GO_TO__]``
|
||||
template<class U> constexpr T value_or( U && v ) const& ; ``[link reference_optional_value_or __GO_TO__]``
|
||||
template<class U> constexpr T value_or( U && v ) && ; ``[link reference_optional_value_or_move __GO_TO__]``
|
||||
|
||||
template<class F> T value_or_eval( F f ) const& ; ``[link reference_optional_value_or_call __GO_TO__]``
|
||||
template<class F> T value_or_eval( F f ) && ; ``[link reference_optional_value_or_call_move __GO_TO__]``
|
||||
template<class F> constexpr T value_or_eval( F f ) const& ; ``[link reference_optional_value_or_call __GO_TO__]``
|
||||
template<class F> constexpr T value_or_eval( F f ) && ; ``[link reference_optional_value_or_call_move __GO_TO__]``
|
||||
|
||||
template<class F> auto map( F f ) const& -> ``['see below]``; ``[link reference_optional_map __GO_TO__]``
|
||||
template<class F> auto map( F f ) & -> ``['see below]``; ``[link reference_optional_map __GO_TO__]``
|
||||
template<class F> auto map( F f ) && -> ``['see below]``; ``[link reference_optional_map_move __GO_TO__]``
|
||||
template<class F> constexpr auto map( F f ) const& -> ``['see below]``; ``[link reference_optional_map __GO_TO__]``
|
||||
template<class F> constexpr auto map( F f ) & -> ``['see below]``; ``[link reference_optional_map __GO_TO__]``
|
||||
template<class F> constexpr auto map( F f ) && -> ``['see below]``; ``[link reference_optional_map_move __GO_TO__]``
|
||||
|
||||
template<class F> auto flat_map( F f ) const& -> ``['see below]``; ``[link reference_optional_flat_map __GO_TO__]``
|
||||
template<class F> auto flat_map( F f ) & -> ``['see below]``; ``[link reference_optional_flat_map __GO_TO__]``
|
||||
template<class F> auto flat_map( F f ) && -> ``['see below]``; ``[link reference_optional_flat_map_move __GO_TO__]``
|
||||
template<class F> constexpr auto flat_map( F f ) const& -> ``['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 __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__]``
|
||||
|
||||
bool has_value() const noexcept ; ``[link reference_optional_operator_bool __GO_TO__]``
|
||||
constexpr bool has_value() const noexcept ; ``[link reference_optional_operator_bool __GO_TO__]``
|
||||
|
||||
explicit operator bool() const noexcept ; ``[link reference_optional_operator_bool __GO_TO__]``
|
||||
constexpr explicit operator bool() const noexcept ; ``[link reference_optional_operator_bool __GO_TO__]``
|
||||
|
||||
bool operator!() const noexcept ; ``[link reference_optional_operator_not __GO_TO__]``
|
||||
|
||||
void reset() noexcept ; ``[link reference_optional_reset __GO_TO__]``
|
||||
constexpr void reset() noexcept ; ``[link reference_optional_reset __GO_TO__]``
|
||||
|
||||
// deprecated methods
|
||||
|
||||
@@ -214,7 +215,7 @@ They are empty, trivially copyable classes with disabled default constructor.
|
||||
void reset ( T const& ) ; ``[link reference_optional_reset_value __GO_TO__]``
|
||||
|
||||
// (deprecated)
|
||||
bool is_initialized() const ; ``[link reference_optional_is_initialized __GO_TO__]``
|
||||
constexpr bool is_initialized() const ; ``[link reference_optional_is_initialized __GO_TO__]``
|
||||
|
||||
// (deprecated)
|
||||
T const& get_value_or( T const& default ) const ; ``[link reference_optional_get_value_or_value __GO_TO__]``
|
||||
@@ -239,9 +240,9 @@ They are empty, trivially copyable classes with disabled default constructor.
|
||||
typedef T* pointer_type;
|
||||
typedef T* pointer_const_type; // no const propagation
|
||||
|
||||
optional () noexcept ; ``[link reference_optional_ref_default_ctor __GO_TO__]``
|
||||
constexpr optional () noexcept ; ``[link reference_optional_ref_default_ctor __GO_TO__]``
|
||||
|
||||
optional ( none_t ) noexcept ; ``[link reference_optional_ref_default_ctor __GO_TO__]``
|
||||
constexpr optional ( none_t ) noexcept ; ``[link reference_optional_ref_default_ctor __GO_TO__]``
|
||||
|
||||
template<class R> optional(R&& r) noexcept ; ``[link reference_optional_ref_value_ctor __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
|
||||
@@ -23,40 +24,40 @@ __SPACE__
|
||||
|
||||
[#reference_optional_constructor]
|
||||
|
||||
[: `optional<T>::optional() noexcept;`]
|
||||
[: `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]
|
||||
[: `constexpr optional<T>::optional( none_t ) noexcept;`]
|
||||
|
||||
[: `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__
|
||||
|
||||
[#reference_optional_constructor_value]
|
||||
|
||||
[: `optional<T>::optional( T const& v )`]
|
||||
[: `constexpr optional<T>::optional( T const& v )`]
|
||||
|
||||
* [*Requires:] `is_copy_constructible<T>::value` is `true`.
|
||||
* [*Effect:] Directly-Constructs an `optional`.
|
||||
@@ -78,7 +79,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_constructor_move_value]
|
||||
|
||||
[: `optional<T>::optional( T&& v )`]
|
||||
[: `constexpr optional<T>::optional( T&& v )`]
|
||||
|
||||
* [*Requires:] `is_move_constructible<T>::value` is `true`.
|
||||
* [*Effect:] Directly-Move-Constructs an `optional`.
|
||||
@@ -99,7 +100,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_constructor_bool_value]
|
||||
|
||||
[: `optional<T>::optional( bool condition, T const& v ) ;` ]
|
||||
[: `constexpr optional<T>::optional( bool condition, T const& v ) ;` ]
|
||||
|
||||
* If condition is true, same as:
|
||||
|
||||
@@ -114,7 +115,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_constructor_optional]
|
||||
|
||||
[: `optional<T>::optional( optional const& rhs );`]
|
||||
[: `constexpr optional<T>::optional( optional const& rhs );`]
|
||||
|
||||
* [*Requires:] `is_copy_constructible<T>::value` is `true`.
|
||||
* [*Effect:] Copy-Constructs an `optional`.
|
||||
@@ -144,7 +145,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_move_constructor_optional]
|
||||
|
||||
[: `optional<T>::optional( optional&& rhs ) noexcept(`['see below]`);`]
|
||||
[: `constexpr optional<T>::optional( optional&& rhs ) noexcept(`['see below]`);`]
|
||||
|
||||
* [*Requires:] `is_move_constructible<T>::value` is `true`.
|
||||
* [*Effect:] Move-constructs an `optional`.
|
||||
@@ -178,7 +179,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_constructor_other_optional]
|
||||
|
||||
[: `template<U> explicit optional<T>::optional( optional<U> const& rhs );`]
|
||||
[: `template<U> constexpr explicit optional<T>::optional( optional<U> const& rhs );`]
|
||||
|
||||
* [*Effect:] Copy-Constructs an `optional`.
|
||||
* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and its
|
||||
@@ -202,7 +203,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_move_constructor_other_optional]
|
||||
|
||||
[: `template<U> explicit optional<T>::optional( optional<U>&& rhs );`]
|
||||
[: `template<U> constexpr explicit optional<T>::optional( optional<U>&& rhs );`]
|
||||
|
||||
* [*Effect:] Move-constructs an `optional`.
|
||||
* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and its
|
||||
@@ -226,7 +227,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_in_place_init]
|
||||
|
||||
[: `template<class... Args> explicit optional<T>::optional( in_place_init_t, Args&&... ars );`]
|
||||
[: `template<class... Args> constexpr explicit optional<T>::optional( in_place_init_t, Args&&... ars );`]
|
||||
|
||||
* [*Requires:] `is_constructible_v<T, Args&&...>` is `true`.
|
||||
* [*Effect:] Initializes the contained value as if direct-non-list-initializing an object of type `T` with the
|
||||
@@ -251,7 +252,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_in_place_init_if]
|
||||
|
||||
[: `template<class... Args> explicit optional<T>::optional( in_place_init_if_t, bool condition, Args&&... ars );`]
|
||||
[: `template<class... Args> constexpr explicit optional<T>::optional( in_place_init_if_t, bool condition, Args&&... ars );`]
|
||||
|
||||
* [*Requires:] `is_constructible_v<T, Args&&...>` is `true`.
|
||||
* [*Effect:] If `condition` is `true`, initializes the contained value as if direct-non-list-initializing an object of type `T` with the arguments `std::forward<Args>(args)...`.
|
||||
@@ -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.
|
||||
@@ -302,7 +303,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_operator_equal_none_t]
|
||||
|
||||
[: `optional& optional<T>::operator= ( none_t ) noexcept;`]
|
||||
[: `constexpr optional& optional<T>::operator= ( none_t ) noexcept;`]
|
||||
|
||||
* [*Effect:] If `*this` is initialized destroys its contained value.
|
||||
* [*Postconditions: ] `*this` is uninitialized.
|
||||
@@ -502,7 +503,7 @@ __SPACE__
|
||||
* [*Postconditions: ] `*this` is [_initialized].
|
||||
* [*Throws:] Whatever the selected `T`'s constructor throws.
|
||||
* [*Exception Safety:] If an exception is thrown during the initialization of `T`, `*this` is ['uninitialized].
|
||||
* [*Notes:] `T` need not be __MOVE_CONSTRUCTIBLE__ or `MoveAssignable`.
|
||||
* [*Notes:] `T` need not be __MOVE_CONSTRUCTIBLE__ or `MoveAssignable`.
|
||||
* [*Example:]
|
||||
``
|
||||
T v;
|
||||
@@ -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].
|
||||
@@ -540,15 +541,15 @@ __SPACE__
|
||||
|
||||
[#reference_optional_reset]
|
||||
|
||||
[: `void optional<T>::reset() noexcept ;`]
|
||||
[: `constexpr void optional<T>::reset() noexcept ;`]
|
||||
* [*Effects:] Same as `operator=( none_t );`
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_get]
|
||||
|
||||
[: `T const& optional<T>::get() const ;`]
|
||||
[: `T& optional<T>::get() ;`]
|
||||
[: `constexpr T const& optional<T>::get() const ;`]
|
||||
[: `constexpr T& optional<T>::get() ;`]
|
||||
|
||||
[: `inline T const& get ( optional<T> const& ) ;`]
|
||||
[: `inline T& get ( optional<T> &) ;`]
|
||||
@@ -563,8 +564,8 @@ __SPACE__
|
||||
|
||||
[#reference_optional_operator_asterisk]
|
||||
|
||||
[: `T const& optional<T>::operator*() const& ;`]
|
||||
[: `T& optional<T>::operator*() &;`]
|
||||
[: `constexpr T const& optional<T>::operator*() const& ;`]
|
||||
[: `constexpr T& optional<T>::operator*() &;`]
|
||||
|
||||
* [*Requires:] `*this` is initialized
|
||||
* [*Returns:] A reference to the contained value
|
||||
@@ -585,7 +586,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_operator_asterisk_move]
|
||||
|
||||
[: `T&& optional<T>::operator*() &&;`]
|
||||
[: `constexpr T&& optional<T>::operator*() &&;`]
|
||||
|
||||
* [*Requires:] `*this` contains a value.
|
||||
* [*Effects:] Equivalent to `return std::move(*val);`.
|
||||
@@ -596,8 +597,8 @@ __SPACE__
|
||||
|
||||
[#reference_optional_value]
|
||||
|
||||
[: `T const& optional<T>::value() const& ;`]
|
||||
[: `T& optional<T>::value() & ;`]
|
||||
[: `constexpr T const& optional<T>::value() const& ;`]
|
||||
[: `constexpr T& optional<T>::value() & ;`]
|
||||
|
||||
* [*Effects:] Equivalent to `return bool(*this) ? *val : throw bad_optional_access();`.
|
||||
* [*Notes:] On compilers that do not support ref-qualifiers on member functions these two overloads are replaced with the classical two: a `const` and non-`const` member functions.
|
||||
@@ -620,7 +621,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_value_move]
|
||||
|
||||
[: `T&& optional<T>::value() && ;`]
|
||||
[: `constexpr T&& optional<T>::value() && ;`]
|
||||
|
||||
* [*Effects:] Equivalent to `return bool(*this) ? std::move(*val) : throw bad_optional_access();`.
|
||||
* [*Notes:] On compilers that do not support ref-qualifiers on member functions this overload is not present.
|
||||
@@ -630,17 +631,25 @@ __SPACE__
|
||||
|
||||
[#reference_optional_value_or]
|
||||
|
||||
[: `template<class U> T optional<T>::value_or(U && v) const& ;`]
|
||||
[: `template<class U = T> constexpr T optional<T>::value_or(U && v) const& ;`]
|
||||
|
||||
* [*Effects:] Equivalent to `if (*this) return **this; else return std::forward<U>(v);`.
|
||||
* [*Remarks:] If `T` is not __COPY_CONSTRUCTIBLE__ or `U &&` is not convertible to `T`, the program is ill-formed.
|
||||
* [*Notes:] On compilers that do not support ref-qualifiers on member functions this overload is replaced with the `const`-qualified member function. On compilers without rvalue reference support the type of `v` becomes `U const&`.
|
||||
* [*Example:]
|
||||
``
|
||||
optional<int> oN, o1(1);
|
||||
|
||||
assert (o1.value_or(9) == 1);
|
||||
assert (oN.value_or(9) == 9);
|
||||
assert (oN.value_or({}) == 0);
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_value_or_move]
|
||||
|
||||
[: `template<class U> T optional<T>::value_or(U && v) && ;`]
|
||||
[: `template<class U> constexpr T optional<T>::value_or(U && v) && ;`]
|
||||
|
||||
* [*Effects:] Equivalent to `if (*this) return std::move(**this); else return std::forward<U>(v);`.
|
||||
* [*Remarks:] If `T` is not __MOVE_CONSTRUCTIBLE__ or `U &&` is not convertible to `T`, the program is ill-formed.
|
||||
@@ -650,7 +659,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_value_or_call]
|
||||
|
||||
[: `template<class F> T optional<T>::value_or_eval(F f) const& ;`]
|
||||
[: `template<class F> constexpr T optional<T>::value_or_eval(F f) const& ;`]
|
||||
|
||||
* [*Requires:] `T` is __COPY_CONSTRUCTIBLE__ and `F` models a __SGI_GENERATOR__ whose result type is convertible to `T`.
|
||||
* [*Effects:] `if (*this) return **this; else return f();`.
|
||||
@@ -677,7 +686,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_value_or_call_move]
|
||||
|
||||
[: `template<class F> T optional<T>::value_or_eval(F f) && ;`]
|
||||
[: `template<class F> constexpr T optional<T>::value_or_eval(F f) && ;`]
|
||||
|
||||
* [*Requires:] `T` is __MOVE_CONSTRUCTIBLE__ and `F` models a __SGI_GENERATOR__ whose result type is convertible to `T`.
|
||||
* [*Effects:] `if (*this) return std::move(**this); else return f();`.
|
||||
@@ -687,8 +696,8 @@ __SPACE__
|
||||
|
||||
[#reference_optional_map]
|
||||
|
||||
[: `template<class F> auto optional<T>::map(F f) const& -> `['see below]` ;`]
|
||||
[: `template<class F> auto optional<T>::map(F f) & -> `['see below]` ;`]
|
||||
[: `template<class F> constexpr auto optional<T>::map(F f) const& -> `['see below]` ;`]
|
||||
[: `template<class F> constexpr auto optional<T>::map(F f) & -> `['see below]` ;`]
|
||||
|
||||
* [*Effects:] `if (*this) return f(**this); else return none;`
|
||||
* [*Notes:] The return type of these overloads is `optional<decltype(f(**this))>`. On compilers that do not support ref-qualifiers on member functions, these two (as well as the next one) overloads are replaced with good old const and non-const overloads.
|
||||
@@ -706,7 +715,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_map_move]
|
||||
|
||||
[: `template<class F> auto optional<T>::map(F f) && -> `['see below]` ;`]
|
||||
[: `template<class F> constexpr auto optional<T>::map(F f) && -> `['see below]` ;`]
|
||||
|
||||
* [*Effects:] `if (*this) return f(std::move(**this)); else return none;`
|
||||
* [*Notes:] The return type of this overload is `optional<decltype(f(istd::move(**this)))>`.
|
||||
@@ -715,8 +724,8 @@ __SPACE__
|
||||
|
||||
[#reference_optional_flat_map]
|
||||
|
||||
[: `template<class F> auto optional<T>::flat_map(F f) const& -> `['see below]` ;`]
|
||||
[: `template<class F> auto optional<T>::flat_map(F f) & -> `['see below]` ;`]
|
||||
[: `template<class F> constexpr auto optional<T>::flat_map(F f) const& -> `['see below]` ;`]
|
||||
[: `template<class F> constexpr auto optional<T>::flat_map(F f) & -> `['see below]` ;`]
|
||||
|
||||
* [*Requires:] The return type of expression `f(**this)` is `optional<U>` for some object or reference type `U`.
|
||||
* [*Effects:] `if (*this) return f(**this); else return none;`
|
||||
@@ -736,7 +745,7 @@ __SPACE__
|
||||
|
||||
[#reference_optional_flat_map_move]
|
||||
|
||||
[: `template<class F> auto optional<T>::flat_map(F f) && -> `['see below]` ;`]
|
||||
[: `template<class F> constexpr auto optional<T>::flat_map(F f) && -> `['see below]` ;`]
|
||||
|
||||
* [*Requires:] The return type of expression `f(std::move(**this))` is `optional<U>` for some object or reference type `U`.
|
||||
* [*Effects:] `if (*this) return f(std::move(**this)); else return none;`
|
||||
@@ -744,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 ;`]
|
||||
@@ -793,8 +822,8 @@ __SPACE__
|
||||
|
||||
[#reference_optional_operator_arrow]
|
||||
|
||||
[: `T const* optional<T>::operator ->() const ;`]
|
||||
[: `T* optional<T>::operator ->() ;`]
|
||||
[: `constexpr T const* optional<T>::operator ->() const ;`]
|
||||
[: `constexpr T* optional<T>::operator ->() ;`]
|
||||
|
||||
* [*Requires: ] `*this` is initialized.
|
||||
* [*Returns:] A pointer to the contained value.
|
||||
@@ -812,44 +841,29 @@ __SPACE__
|
||||
|
||||
[#reference_optional_operator_bool]
|
||||
|
||||
[: `explicit optional<T>::operator bool() const noexcept ;`]
|
||||
[: `bool optional<T>::has_value() const noexcept ;`]
|
||||
[: `constexpr explicit optional<T>::operator bool() const noexcept ;`]
|
||||
[: `constexpr bool optional<T>::has_value() const noexcept ;`]
|
||||
|
||||
* [*Returns:] `get_ptr() != 0`.
|
||||
* [*Notes:] On compilers that do not support explicit conversion operators this falls back to safe-bool idiom.
|
||||
* [*Example:]
|
||||
``
|
||||
optional<T> def ;
|
||||
assert ( def == 0 );
|
||||
optional<T> opt ( v ) ;
|
||||
assert ( opt );
|
||||
assert ( opt != 0 );
|
||||
optional<int> oN;
|
||||
assert (!oN);
|
||||
assert (!oN.has_value());
|
||||
|
||||
optional<int> o1(1);
|
||||
assert (o1);
|
||||
assert (o1.has_value());
|
||||
assert (!!o1); // the "double-bang" idiom
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_operator_not]
|
||||
|
||||
[: `bool optional<T>::operator!() noexcept ;`]
|
||||
|
||||
* [*Returns:] If `*this` is uninitialized, `true`; else `false`.
|
||||
* [*Notes:] This operator is provided for those compilers which can't
|
||||
use the ['unspecified-bool-type operator] in certain boolean contexts.
|
||||
* [*Example:]
|
||||
``
|
||||
optional<T> opt ;
|
||||
assert ( !opt );
|
||||
*opt = some_T ;
|
||||
|
||||
// Notice the "double-bang" idiom here.
|
||||
assert ( !!opt ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_is_initialized]
|
||||
|
||||
[: `bool optional<T>::is_initialized() const ;`]
|
||||
[: `constexpr bool optional<T>::is_initialized() const ;`]
|
||||
|
||||
* [*Deprecated:] Same as `explicit operator bool () ;`
|
||||
|
||||
@@ -862,8 +876,8 @@ __SPACE__
|
||||
|
||||
[#reference_optional_ref_default_ctor]
|
||||
|
||||
[: `optional<T&>::optional() noexcept;`]
|
||||
[: `optional<T&>::optional(none_t) noexcept;`]
|
||||
[: `constexpr optional<T&>::optional() noexcept;`]
|
||||
[: `constexpr optional<T&>::optional(none_t) noexcept;`]
|
||||
|
||||
* [*Postconditions:] `bool(*this) == false`; `*this` refers to nothing.
|
||||
|
||||
@@ -963,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]
|
||||
|
||||
+56
-2
@@ -9,7 +9,62 @@
|
||||
]
|
||||
|
||||
|
||||
[section Dependencies and Portability]
|
||||
[section Dependencies and Portability][#minimum_system_requirements]
|
||||
|
||||
|
||||
[section Minimum System Requirements]
|
||||
This library requires C++11 as minimum. However, in C++11 some features are disabled.
|
||||
|
||||
[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]
|
||||
|
||||
|
||||
[section Dependencies]
|
||||
The implementation uses the following other Boost modules:
|
||||
@@ -17,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]
|
||||
|
||||
+53
-2
@@ -1,7 +1,7 @@
|
||||
[/
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2015 - 2023 Andrzej Krzemienski
|
||||
Copyright (c) 2015 - 2026 Andrzej Krzemienski
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -11,6 +11,57 @@
|
||||
|
||||
[section:relnotes Release Notes]
|
||||
|
||||
[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]
|
||||
|
||||
* *Breaking change.* Dropped support for C++03. C++11 is now the required minimum; at least some C++11 features.
|
||||
@@ -22,7 +73,7 @@
|
||||
* *Warning.* In the future releases we intend to introduce the range interface
|
||||
into `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`.
|
||||
on predicates such as `std::ranges::range`.
|
||||
* Tags `in_place_init` and `in_place_init_if` become `inline constexpr` and therewith leave smaller footprint in the executable. This addresses [@https://github.com/boostorg/optional/issues/103 issue #103].
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
// Copyright (C) 2024 Ryan Malcolm Underwood.
|
||||
// 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 authors at:
|
||||
// akrzemi1@gmail.com
|
||||
// typenametea@gmail.com
|
||||
//
|
||||
//
|
||||
// This header provides definitions required by any specialization of
|
||||
// optional<>.
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_COMMON_DEFS_01FEB2026_HPP
|
||||
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_COMMON_DEFS_01FEB2026_HPP
|
||||
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/core/addressof.hpp>
|
||||
#include <type_traits>
|
||||
#include <boost/optional/detail/optional_factory_support.hpp>
|
||||
|
||||
#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
|
||||
|
||||
#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
|
||||
# define BOOST_OPTIONAL_DECAY(T) BOOST_DEDUCED_TYPENAME boost::decay<T>::type
|
||||
# define BOOST_OPTIONAL_IS_TAGGED(TAG, U) boost::is_base_of<TAG, BOOST_OPTIONAL_DECAY(U)>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename T> class optional;
|
||||
|
||||
|
||||
// Boost-wide tags for recognizing "factories": a C++03 workaround
|
||||
// for perfect forwarding.
|
||||
class in_place_factory_base;
|
||||
class typed_in_place_factory_base;
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
// Traits for recognizing in-place factories
|
||||
namespace boost { namespace optional_detail {
|
||||
|
||||
template <typename U>
|
||||
struct is_in_place_factory : BOOST_OPTIONAL_IS_TAGGED(boost::in_place_factory_base, U) {};
|
||||
|
||||
template <typename U>
|
||||
struct is_typed_in_place_factory : BOOST_OPTIONAL_IS_TAGGED(boost::typed_in_place_factory_base, U) {};
|
||||
|
||||
}}
|
||||
|
||||
|
||||
|
||||
/** This is a set of declarations that repeat those from the Standard Library
|
||||
header <utility> but without having to drag its entire content. They also
|
||||
add missing capabilities, like constexpr, in older compiler versions.
|
||||
*/
|
||||
namespace boost { namespace optional_detail {
|
||||
|
||||
template <typename T>
|
||||
T declval_();
|
||||
|
||||
template <class T>
|
||||
inline constexpr T&& forward_(typename ::std::remove_reference<T>::type& t) noexcept
|
||||
{
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline constexpr T&& forward_(typename ::std::remove_reference<T>::type&& t) noexcept
|
||||
{
|
||||
static_assert(!::std::is_lvalue_reference<T>::value, "Can not forward an rvalue as an lvalue.");
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline constexpr typename ::std::remove_reference<T>::type&& move_(T&& t) noexcept
|
||||
{
|
||||
return static_cast<typename ::std::remove_reference<T>::type&&>(t);
|
||||
}
|
||||
|
||||
}} // namespace boost::optional_detail
|
||||
|
||||
|
||||
/** This is a set of declarations that are not part of this library's interface.
|
||||
They are implementation details.
|
||||
*/
|
||||
namespace boost { namespace optional_detail {
|
||||
|
||||
/** This struct is used for tagging types that want to be recognized as
|
||||
`optional`. If your class inherits directly or indirectly from `optional_tag`
|
||||
the type traits and overloads will treat it as `optional<>`.
|
||||
*/
|
||||
struct optional_tag {};
|
||||
|
||||
/** `optional_value_type`: given type `X`:
|
||||
* if `X` is an instance of `boost::optional`, returns its value_type,
|
||||
* otherwise we get a SFINAE-able error.
|
||||
*/
|
||||
template <typename X>
|
||||
struct optional_value_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename U>
|
||||
struct optional_value_type< ::boost::optional<U> >
|
||||
{
|
||||
typedef U type;
|
||||
};
|
||||
|
||||
|
||||
/** This is an approximation of a 1-argument C++17 std::invoke_result.
|
||||
*/
|
||||
template <typename F, typename Ref, typename Rslt = decltype(declval_<F>()(declval_<Ref>()))>
|
||||
struct result_of
|
||||
{
|
||||
typedef Rslt type;
|
||||
};
|
||||
|
||||
/** This type trait returns the following given the expression `f(ref)`:
|
||||
* if the result is a specialization of `boost::optional`: its value_type,
|
||||
* otherwise a SFINAE-able error.
|
||||
*/
|
||||
template <typename F, typename Ref, typename Rslt = typename optional_value_type<typename result_of<F, Ref>::type>::type>
|
||||
struct result_value_type
|
||||
{
|
||||
typedef Rslt type;
|
||||
};
|
||||
|
||||
}} // namespace boost::optional_detail
|
||||
|
||||
|
||||
/** The following two tags are intended to be used by library users.
|
||||
The additional namespace is used in order to prevent the ADL from
|
||||
dragging all functions from namespace `boost` in any unqualified name lookup
|
||||
when these tags are involved.
|
||||
*/
|
||||
namespace boost {
|
||||
|
||||
namespace optional_ns {
|
||||
|
||||
/// a tag for in-place initialization of contained value
|
||||
struct in_place_init_t
|
||||
{
|
||||
struct init_tag{};
|
||||
BOOST_CONSTEXPR explicit in_place_init_t(init_tag){}
|
||||
};
|
||||
BOOST_INLINE_CONSTEXPR in_place_init_t in_place_init ((in_place_init_t::init_tag()));
|
||||
|
||||
/// a tag for conditional in-place initialization of contained value
|
||||
struct in_place_init_if_t
|
||||
{
|
||||
struct init_tag{};
|
||||
BOOST_CONSTEXPR explicit in_place_init_if_t(init_tag){}
|
||||
};
|
||||
BOOST_INLINE_CONSTEXPR in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag()));
|
||||
|
||||
} // namespace optional_ns
|
||||
|
||||
using optional_ns::in_place_init_t;
|
||||
using optional_ns::in_place_init;
|
||||
using optional_ns::in_place_init_if_t;
|
||||
using optional_ns::in_place_init_if;
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_OPTIONAL_DETAIL_OPTIONAL_COMMON_DEFS_01FEB2026_HPP
|
||||
@@ -27,10 +27,4 @@ namespace boost_optional_detail
|
||||
}
|
||||
}
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class in_place_factory_base ;
|
||||
class typed_in_place_factory_base ;
|
||||
}
|
||||
|
||||
#endif // header guard
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_HASH_AJK_20MAY2022_HPP
|
||||
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_HASH_AJK_20MAY2022_HPP
|
||||
|
||||
#include <boost/optional/optional_fwd.hpp>
|
||||
//#include <boost/optional/optional_fwd.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#if !defined(BOOST_OPTIONAL_CONFIG_DO_NOT_SPECIALIZE_STD_HASH) && !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2014 - 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 authors at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
// akrzemi1@gmail.com
|
||||
//
|
||||
// You can file a GitHub issue at:
|
||||
// https://github.com/boostorg/optional/issues
|
||||
|
||||
|
||||
// This header provides definitions rof nonmember functions that still constitute
|
||||
// the interface for class optional<>.
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_NONMEMBER_INTERFACE_01FEB2026_HPP
|
||||
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_NONMEMBER_INTERFACE_01FEB2026_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
|
||||
template <class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
optional<BOOST_OPTIONAL_DECAY(T)> make_optional ( T && v )
|
||||
{
|
||||
return optional<BOOST_OPTIONAL_DECAY(T)>(optional_detail::forward_<T>(v));
|
||||
}
|
||||
|
||||
// Returns optional<T>(cond,v)
|
||||
template <class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
optional<BOOST_OPTIONAL_DECAY(T)> make_optional ( bool cond, T && v )
|
||||
{
|
||||
return optional<BOOST_OPTIONAL_DECAY(T)>(cond,optional_detail::forward_<T>(v));
|
||||
}
|
||||
|
||||
|
||||
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
|
||||
// No-throw
|
||||
template <class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
|
||||
get ( optional<T> const& opt )
|
||||
{
|
||||
return opt.get() ;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
|
||||
get ( optional<T>& opt )
|
||||
{
|
||||
return opt.get() ;
|
||||
}
|
||||
|
||||
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
|
||||
// No-throw
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
|
||||
get ( optional<T> const* opt )
|
||||
{
|
||||
return opt->get_ptr() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
|
||||
get ( optional<T>* opt )
|
||||
{
|
||||
return opt->get_ptr() ;
|
||||
}
|
||||
|
||||
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
|
||||
// No-throw
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
|
||||
get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
|
||||
{
|
||||
return opt.get_value_or(v) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
|
||||
get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
|
||||
{
|
||||
return opt.get_value_or(v) ;
|
||||
}
|
||||
|
||||
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
|
||||
// No-throw
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
|
||||
get_pointer ( optional<T> const& opt )
|
||||
{
|
||||
return opt.get_ptr() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline BOOST_CXX14_CONSTEXPR
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
|
||||
get_pointer ( optional<T>& opt )
|
||||
{
|
||||
return opt.get_ptr() ;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_OPTIONAL_DETAIL_OPTIONAL_NONMEMBER_INTERFACE_01FEB2026_HPP
|
||||
@@ -13,9 +13,21 @@
|
||||
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP
|
||||
|
||||
#ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT
|
||||
#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_UNION_IMPLEMENTATION
|
||||
# define BOOST_OPTIONAL_TT_PREFIX ::std
|
||||
#else
|
||||
# define BOOST_OPTIONAL_TT_PREFIX boost
|
||||
# define BOOST_OPTIONAL_REQUIRES(...) BOOST_DEDUCED_TYPENAME boost::enable_if_c<__VA_ARGS__::value, bool>::type = false
|
||||
#endif
|
||||
|
||||
# define BOOST_OPTIONAL_TT_TYPE(...) BOOST_DEDUCED_TYPENAME BOOST_OPTIONAL_TT_PREFIX::__VA_ARGS__::type
|
||||
# define BOOST_OPTIONAL_TT_PRED(...) BOOST_OPTIONAL_TT_PREFIX::__VA_ARGS__::value
|
||||
|
||||
# if 1
|
||||
|
||||
@@ -29,17 +41,17 @@ template <class From>
|
||||
void prevent_binding_rvalue()
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
|
||||
static_assert(boost::is_lvalue_reference<From>::value,
|
||||
static_assert(BOOST_OPTIONAL_TT_PRED(is_lvalue_reference<From>),
|
||||
"binding rvalue references to optional lvalue references is disallowed");
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type& forward_reference(T&& r)
|
||||
BOOST_OPTIONAL_TT_TYPE(remove_reference<T>)& forward_reference(T&& r)
|
||||
{
|
||||
static_assert(boost::is_lvalue_reference<T>::value,
|
||||
static_assert(BOOST_OPTIONAL_TT_PRED(is_lvalue_reference<T>),
|
||||
"binding rvalue references to optional lvalue references is disallowed");
|
||||
return optional_detail::forward<T>(r);
|
||||
return optional_detail::forward_<T>(r);
|
||||
}
|
||||
|
||||
#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
@@ -48,14 +60,14 @@ BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type& forward_reference(T&& r
|
||||
template <class T>
|
||||
struct is_const_integral
|
||||
{
|
||||
static const bool value = boost::is_const<T>::value && boost::is_integral<T>::value;
|
||||
static const bool value = BOOST_OPTIONAL_TT_PRED(is_const<T>) && BOOST_OPTIONAL_TT_PRED(is_integral<T>);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_const_integral_bad_for_conversion
|
||||
{
|
||||
#if (!defined BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES) && (defined BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT)
|
||||
static const bool value = boost::is_const<T>::value && boost::is_integral<T>::value;
|
||||
static const bool value = is_const_integral<T>::value;
|
||||
#else
|
||||
static const bool value = false;
|
||||
#endif
|
||||
@@ -90,15 +102,15 @@ struct is_optional_< ::boost::optional<U> >
|
||||
template <class T>
|
||||
struct is_no_optional
|
||||
{
|
||||
static const bool value = !is_optional_<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>::value;
|
||||
static const bool value = !is_optional_<BOOST_OPTIONAL_DECAY(T)>::value;
|
||||
};
|
||||
|
||||
|
||||
template <class T, class U>
|
||||
struct is_same_decayed
|
||||
{
|
||||
static const bool value = ::boost::is_same<T, BOOST_DEDUCED_TYPENAME ::boost::remove_reference<U>::type>::value
|
||||
|| ::boost::is_same<T, const BOOST_DEDUCED_TYPENAME ::boost::remove_reference<U>::type>::value;
|
||||
static const bool value = BOOST_OPTIONAL_TT_PRED(is_same<T, BOOST_OPTIONAL_TT_TYPE(remove_reference<U>)>)
|
||||
|| BOOST_OPTIONAL_TT_PRED(is_same<T, const BOOST_OPTIONAL_TT_TYPE(remove_reference<U>)>);
|
||||
};
|
||||
|
||||
template <class T, class U>
|
||||
@@ -123,152 +135,165 @@ public:
|
||||
typedef T* pointer_type;
|
||||
typedef T* pointer_const_type;
|
||||
|
||||
optional() BOOST_NOEXCEPT : ptr_() {}
|
||||
optional(none_t) BOOST_NOEXCEPT : ptr_() {}
|
||||
BOOST_CONSTEXPR optional() BOOST_NOEXCEPT : ptr_() {}
|
||||
BOOST_CONSTEXPR optional(none_t) BOOST_NOEXCEPT : ptr_() {}
|
||||
|
||||
template <class U>
|
||||
explicit optional(const optional<U&>& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {}
|
||||
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_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_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>
|
||||
explicit optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c<detail::is_same_decayed<T, U>::value && detail::is_const_integral_bad_for_conversion<U>::value, bool>::type = true) BOOST_NOEXCEPT
|
||||
: ptr_(boost::addressof(rhs)) {}
|
||||
|
||||
template <class U>
|
||||
optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c<detail::is_same_decayed<T, U>::value && !detail::is_const_integral_bad_for_conversion<U>::value, bool>::type = true) BOOST_NOEXCEPT
|
||||
: ptr_(boost::addressof(rhs)) {}
|
||||
|
||||
optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; }
|
||||
template <class U>
|
||||
optional& operator=(const optional<U&>& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; }
|
||||
optional& operator=(none_t) BOOST_NOEXCEPT { ptr_ = 0; return *this; }
|
||||
BOOST_CXX14_CONSTEXPR optional& operator=(const optional<U&>& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; }
|
||||
BOOST_CXX14_CONSTEXPR optional& operator=(none_t) BOOST_NOEXCEPT { ptr_ = 0; return *this; }
|
||||
|
||||
|
||||
void swap(optional& rhs) BOOST_NOEXCEPT { std::swap(ptr_, rhs.ptr_); }
|
||||
T& get() const { BOOST_ASSERT(ptr_); return *ptr_; }
|
||||
BOOST_CXX14_CONSTEXPR void swap(optional& rhs) BOOST_NOEXCEPT { ::std::swap(ptr_, rhs.ptr_); }
|
||||
constexpr T& get() const { return BOOST_OPTIONAL_ASSERTED_EXPRESSION(ptr_, *ptr_); }
|
||||
|
||||
T* get_ptr() const BOOST_NOEXCEPT { return ptr_; }
|
||||
T* operator->() const { BOOST_ASSERT(ptr_); return ptr_; }
|
||||
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_); }
|
||||
|
||||
T& value() const
|
||||
constexpr T& value() const
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return this->get();
|
||||
else
|
||||
throw_exception(bad_optional_access());
|
||||
return this->is_initialized() ?
|
||||
this->get() :
|
||||
(boost::throw_exception(boost::bad_optional_access()), this->get());
|
||||
}
|
||||
|
||||
explicit operator bool() const BOOST_NOEXCEPT { return ptr_ != 0; }
|
||||
constexpr explicit operator bool() const BOOST_NOEXCEPT { return ptr_ != 0; }
|
||||
|
||||
void reset() BOOST_NOEXCEPT { ptr_ = 0; }
|
||||
BOOST_CXX14_CONSTEXPR void reset() BOOST_NOEXCEPT { ptr_ = 0; }
|
||||
|
||||
bool is_initialized() const BOOST_NOEXCEPT { return ptr_ != 0; }
|
||||
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>
|
||||
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>
|
||||
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
|
||||
|
||||
optional(T&& /* rhs */) BOOST_NOEXCEPT { detail::prevent_binding_rvalue<T&&>(); }
|
||||
|
||||
template <class R>
|
||||
optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::no_unboxing_cond<T, R>, bool>::type = true) BOOST_NOEXCEPT
|
||||
template <class R, BOOST_OPTIONAL_REQUIRES(detail::no_unboxing_cond<T, R>)>
|
||||
BOOST_CXX14_CONSTEXPR optional(R&& r) BOOST_NOEXCEPT
|
||||
: ptr_(boost::addressof(r)) { detail::prevent_binding_rvalue<R>(); }
|
||||
|
||||
template <class R>
|
||||
optional(bool cond, R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) BOOST_NOEXCEPT
|
||||
template <class R, BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<R>)>
|
||||
BOOST_CXX14_CONSTEXPR optional(bool cond, R&& r) BOOST_NOEXCEPT
|
||||
: ptr_(cond ? boost::addressof(r) : 0) { detail::prevent_binding_rvalue<R>(); }
|
||||
|
||||
template <class R>
|
||||
BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, optional<T&>&>::type
|
||||
template <class R, BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<R>)>
|
||||
BOOST_CXX14_CONSTEXPR optional<T&>&
|
||||
operator=(R&& r) BOOST_NOEXCEPT { detail::prevent_binding_rvalue<R>(); ptr_ = boost::addressof(r); return *this; }
|
||||
|
||||
template <class R>
|
||||
void emplace(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) BOOST_NOEXCEPT
|
||||
template <class R, BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<R>)>
|
||||
BOOST_CXX14_CONSTEXPR void emplace(R&& r) BOOST_NOEXCEPT
|
||||
{ detail::prevent_binding_rvalue<R>(); ptr_ = boost::addressof(r); }
|
||||
|
||||
template <class R>
|
||||
T& get_value_or(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) const BOOST_NOEXCEPT
|
||||
template <class R, BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<R>)>
|
||||
BOOST_CXX14_CONSTEXPR T& get_value_or(R&& r) const BOOST_NOEXCEPT
|
||||
{ detail::prevent_binding_rvalue<R>(); return ptr_ ? *ptr_ : r; }
|
||||
|
||||
template <class R>
|
||||
T& value_or(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) const BOOST_NOEXCEPT
|
||||
template <class R, BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<R>)>
|
||||
BOOST_CXX14_CONSTEXPR T& value_or(R&& r) const BOOST_NOEXCEPT
|
||||
{ detail::prevent_binding_rvalue<R>(); return ptr_ ? *ptr_ : r; }
|
||||
|
||||
template <class R>
|
||||
void reset(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) BOOST_NOEXCEPT
|
||||
template <class R, BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<R>)>
|
||||
BOOST_CXX14_CONSTEXPR void reset(R&& r) BOOST_NOEXCEPT
|
||||
{ detail::prevent_binding_rvalue<R>(); ptr_ = boost::addressof(r); }
|
||||
|
||||
template <class F>
|
||||
T& value_or_eval(F f) const { return ptr_ ? *ptr_ : detail::forward_reference(f()); }
|
||||
BOOST_CXX14_CONSTEXPR T& value_or_eval(F f) const { return ptr_ ? *ptr_ : detail::forward_reference(f()); }
|
||||
|
||||
#else // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
|
||||
|
||||
// the following two implement a 'conditionally explicit' constructor
|
||||
template <class U>
|
||||
explicit optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if_c<detail::no_unboxing_cond<T, U>::value && detail::is_const_integral_bad_for_conversion<U>::value, bool>::type = true) BOOST_NOEXCEPT
|
||||
template <class U,
|
||||
BOOST_OPTIONAL_REQUIRES(detail::no_unboxing_cond<T, U>),
|
||||
BOOST_OPTIONAL_REQUIRES(detail::is_const_integral_bad_for_conversion<U>)>
|
||||
BOOST_CXX14_CONSTEXPR explicit optional(U& v) BOOST_NOEXCEPT
|
||||
: ptr_(boost::addressof(v)) { }
|
||||
|
||||
template <class U>
|
||||
optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if_c<detail::no_unboxing_cond<T, U>::value && !detail::is_const_integral_bad_for_conversion<U>::value, bool>::type = true) BOOST_NOEXCEPT
|
||||
template <class U,
|
||||
BOOST_OPTIONAL_REQUIRES(detail::no_unboxing_cond<T, U>),
|
||||
BOOST_OPTIONAL_REQUIRES(!detail::is_const_integral_bad_for_conversion<U>)>
|
||||
BOOST_CXX14_CONSTEXPR optional(U& v) BOOST_NOEXCEPT
|
||||
: ptr_(boost::addressof(v)) { }
|
||||
|
||||
template <class U>
|
||||
optional(bool cond, U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) BOOST_NOEXCEPT : ptr_(cond ? boost::addressof(v) : 0) {}
|
||||
template <class U,
|
||||
BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<U>)>
|
||||
BOOST_CXX14_CONSTEXPR optional(bool cond, U& v) BOOST_NOEXCEPT : ptr_(cond ? boost::addressof(v) : 0) {}
|
||||
|
||||
template <class U>
|
||||
BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, optional<T&>&>::type
|
||||
operator=(U& v) BOOST_NOEXCEPT
|
||||
template <class U,
|
||||
BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<U>)>
|
||||
BOOST_CXX14_CONSTEXPR
|
||||
optional<T&>& operator=(U& v) BOOST_NOEXCEPT
|
||||
{
|
||||
detail::prevent_assignment_from_false_const_integral<U>();
|
||||
ptr_ = boost::addressof(v); return *this;
|
||||
}
|
||||
|
||||
template <class U>
|
||||
void emplace(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) BOOST_NOEXCEPT
|
||||
template <class U,
|
||||
BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<U>)>
|
||||
BOOST_CXX14_CONSTEXPR void emplace(U& v) BOOST_NOEXCEPT
|
||||
{ ptr_ = boost::addressof(v); }
|
||||
|
||||
template <class U>
|
||||
T& get_value_or(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) const BOOST_NOEXCEPT
|
||||
template <class U,
|
||||
BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<U>)>
|
||||
BOOST_CXX14_CONSTEXPR T& get_value_or(U& v) const BOOST_NOEXCEPT
|
||||
{ return ptr_ ? *ptr_ : v; }
|
||||
|
||||
template <class U>
|
||||
T& value_or(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) const BOOST_NOEXCEPT
|
||||
{ return ptr_ ? *ptr_ : v; }
|
||||
template <class U,
|
||||
BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<U>)>
|
||||
BOOST_CXX14_CONSTEXPR T& value_or(U& v) const BOOST_NOEXCEPT
|
||||
{ return ptr_ ? *ptr_ : v; }
|
||||
|
||||
template <class U>
|
||||
void reset(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) BOOST_NOEXCEPT
|
||||
template <class U,
|
||||
BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<U>)>
|
||||
BOOST_CXX14_CONSTEXPR void reset(U& v) BOOST_NOEXCEPT
|
||||
{ ptr_ = boost::addressof(v); }
|
||||
|
||||
template <class F>
|
||||
T& value_or_eval(F f) const { return ptr_ ? *ptr_ : f(); }
|
||||
BOOST_CXX14_CONSTEXPR T& value_or_eval(F f) const { return ptr_ ? *ptr_ : f(); }
|
||||
|
||||
#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void swap ( optional<T&>& x, optional<T&>& y) BOOST_NOEXCEPT
|
||||
BOOST_CXX14_CONSTEXPR void swap ( optional<T&>& x, optional<T&>& y) BOOST_NOEXCEPT
|
||||
{
|
||||
x.swap(y);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2015, 2024 Andrzej Krzemienski.
|
||||
// Copyright (C) 2015, 2024, 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
|
||||
@@ -25,32 +25,32 @@ namespace boost {
|
||||
//
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
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
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator < ( optional<T> const& x, optional<T> const& y )
|
||||
{ return !y ? false : (!x ? true : (*x) < (*y)); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator != ( optional<T> const& x, optional<T> const& y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator > ( optional<T> const& x, optional<T> const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator <= ( optional<T> const& x, optional<T> const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
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
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator == ( optional<T> const& x, T const& y )
|
||||
{ return x && (*x == y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator < ( optional<T> const& x, T const& y )
|
||||
{ return (!x) || (*x < y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator != ( optional<T> const& x, T const& y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator > ( optional<T> const& x, T const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator <= ( optional<T> const& x, T const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
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
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator == ( T const& x, optional<T> const& y )
|
||||
{ return y && (x == *y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator < ( T const& x, optional<T> const& y )
|
||||
{ return y && (x < *y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator != ( T const& x, optional<T> const& y )
|
||||
{ return !( x == y ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator > ( T const& x, optional<T> const& y )
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator <= ( T const& x, optional<T> const& y )
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator >= ( T const& x, optional<T> const& y )
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
@@ -128,33 +128,33 @@ bool operator >= ( T const& x, optional<T> const& y )
|
||||
//
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator == ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
|
||||
{ return !x; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator < ( optional<T> const&, none_t )
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator < ( optional<T> const&, none_t ) BOOST_NOEXCEPT
|
||||
{ return false; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator != ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
|
||||
{ return bool(x); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator > ( optional<T> const& x, none_t y )
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator > ( optional<T> const& x, none_t y ) BOOST_NOEXCEPT
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator <= ( optional<T> const& x, none_t y )
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator <= ( optional<T> const& x, none_t y ) BOOST_NOEXCEPT
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator >= ( optional<T> const& x, none_t y )
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator >= ( optional<T> const& x, none_t y ) BOOST_NOEXCEPT
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
//
|
||||
@@ -162,33 +162,33 @@ bool operator >= ( optional<T> const& x, none_t y )
|
||||
//
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator == ( none_t , optional<T> const& y ) BOOST_NOEXCEPT
|
||||
{ return !y; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator < ( none_t , optional<T> const& y )
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator < ( none_t , optional<T> const& y ) BOOST_NOEXCEPT
|
||||
{ return bool(y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator != ( none_t, optional<T> const& y ) BOOST_NOEXCEPT
|
||||
{ return bool(y); }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator > ( none_t x, optional<T> const& y )
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator > ( none_t x, optional<T> const& y ) BOOST_NOEXCEPT
|
||||
{ return y < x ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator <= ( none_t x, optional<T> const& y )
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator <= ( none_t x, optional<T> const& y ) BOOST_NOEXCEPT
|
||||
{ return !( y < x ) ; }
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
bool operator >= ( none_t x, optional<T> const& y )
|
||||
inline BOOST_CONSTEXPR
|
||||
bool operator >= ( none_t x, optional<T> const& y ) BOOST_NOEXCEPT
|
||||
{ return !( x < y ) ; }
|
||||
|
||||
} // namespace boost
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// 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)
|
||||
# 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
|
||||
@@ -54,7 +54,7 @@ struct swap_selector<true>
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
|
||||
# define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) optional_detail::move(EXPR_)
|
||||
# define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) optional_detail::move_(EXPR_)
|
||||
#else
|
||||
# define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) EXPR_
|
||||
#endif
|
||||
|
||||
@@ -54,7 +54,7 @@ class tc_optional_base : public optional_tag
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
construct(optional_detail::forward<Expr>(expr),tag);
|
||||
construct(optional_detail::forward_<Expr>(expr),tag);
|
||||
}
|
||||
|
||||
// tc_optional_base& operator= ( tc_optional_base const& ) = default;
|
||||
@@ -102,7 +102,7 @@ class tc_optional_base : public optional_tag
|
||||
template<class Expr, class ExprPtr>
|
||||
void assign_expr ( Expr&& expr, ExprPtr const* tag )
|
||||
{
|
||||
construct(optional_detail::forward<Expr>(expr),tag);
|
||||
construct(optional_detail::forward_<Expr>(expr),tag);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -138,14 +138,14 @@ class tc_optional_base : public optional_tag
|
||||
template<class... Args>
|
||||
void construct ( in_place_init_t, Args&&... args )
|
||||
{
|
||||
m_storage = value_type( optional_detail::forward<Args>(args)... ) ;
|
||||
m_storage = value_type( optional_detail::forward_<Args>(args)... ) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
void emplace_assign ( Args&&... args )
|
||||
{
|
||||
construct(in_place_init, optional_detail::forward<Args>(args)...);
|
||||
construct(in_place_init, optional_detail::forward_<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
@@ -153,7 +153,7 @@ class tc_optional_base : public optional_tag
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
construct(in_place_init, optional_detail::forward<Args>(args)...);
|
||||
construct(in_place_init, optional_detail::forward_<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
@@ -162,7 +162,7 @@ class tc_optional_base : public optional_tag
|
||||
m_initialized(false)
|
||||
{
|
||||
if ( cond )
|
||||
construct(in_place_init, optional_detail::forward<Args>(args)...);
|
||||
construct(in_place_init, optional_detail::forward_<Args>(args)...);
|
||||
}
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
@@ -207,7 +207,7 @@ class tc_optional_base : public optional_tag
|
||||
template<class Expr>
|
||||
void construct ( Expr&& expr, void const* )
|
||||
{
|
||||
m_storage = value_type(optional_detail::forward<Expr>(expr)) ;
|
||||
m_storage = value_type(optional_detail::forward_<Expr>(expr)) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ class tc_optional_base : public optional_tag
|
||||
template<class Expr>
|
||||
void assign_expr_to_initialized ( Expr&& expr, void const* )
|
||||
{
|
||||
assign_value( optional_detail::forward<Expr>(expr) );
|
||||
assign_value( optional_detail::forward_<Expr>(expr) );
|
||||
}
|
||||
|
||||
#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright (C) 2024 Ryan Malcolm Underwood.
|
||||
//
|
||||
// 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:
|
||||
// typenametea@gmail.com
|
||||
|
||||
#ifndef BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_UTILITY_RMU_06OCT2024_HPP
|
||||
#define BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_UTILITY_RMU_06OCT2024_HPP
|
||||
|
||||
namespace boost {
|
||||
namespace optional_detail {
|
||||
|
||||
// Workaround: forward and move aren't constexpr in C++11
|
||||
template <class T>
|
||||
inline constexpr T&& forward(typename boost::remove_reference<T>::type& t) noexcept
|
||||
{
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline constexpr T&& forward(typename boost::remove_reference<T>::type&& t) noexcept
|
||||
{
|
||||
static_assert(!boost::is_lvalue_reference<T>::value, "Can not forward an rvalue as an lvalue.");
|
||||
return static_cast<T&&>(t);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline constexpr typename boost::remove_reference<T>::type&& move(T&& t) noexcept
|
||||
{
|
||||
return static_cast<typename boost::remove_reference<T>::type&&>(t);
|
||||
}
|
||||
|
||||
} // namespace optional_detail
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,722 @@
|
||||
// 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_UNION_OPTIONAL_01FEB2026_HPP
|
||||
#define BOOST_OPTIONAL_DETAIL_UNION_OPTIONAL_01FEB2026_HPP
|
||||
|
||||
//#include <initializer_list>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/invoke_swap.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
#include <boost/optional/bad_optional_access.hpp>
|
||||
|
||||
|
||||
|
||||
// This macro shall be put in the position of a template parameter.
|
||||
// It emulates the requires clause.
|
||||
# define BOOST_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false
|
||||
|
||||
|
||||
# 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 {
|
||||
|
||||
template <class...>
|
||||
struct conjunction : ::std::true_type {};
|
||||
|
||||
template <class B1>
|
||||
struct conjunction<B1> : B1 {};
|
||||
|
||||
template <class B1, class... Bn>
|
||||
struct conjunction<B1, Bn...>
|
||||
: ::std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
|
||||
|
||||
}}
|
||||
|
||||
namespace boost { namespace optional_detail {
|
||||
|
||||
// Tag to indicate a special-purpose constructor
|
||||
BOOST_INLINE_VARIABLE constexpr struct trivial_init_t{} trivial_init{};
|
||||
|
||||
|
||||
template <class T>
|
||||
union constexpr_union_storage_t
|
||||
{
|
||||
static_assert(::std::is_trivially_destructible<T>::value, "!!");
|
||||
|
||||
unsigned char dummy_;
|
||||
T value_;
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
template <class T>
|
||||
union fallback_union_storage_t
|
||||
{
|
||||
unsigned char dummy_;
|
||||
T value_;
|
||||
|
||||
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`.
|
||||
};
|
||||
|
||||
|
||||
// `guarded_storage` is a union + a flag indicating if a `T` has been initialized.
|
||||
// this way the destructor knows if it should destroy the `T`.
|
||||
template <class T>
|
||||
struct constexpr_guarded_storage
|
||||
{
|
||||
static_assert(::std::is_trivially_destructible<T>::value, "!!");
|
||||
|
||||
bool init_;
|
||||
constexpr_union_storage_t<T> storage_;
|
||||
|
||||
constexpr constexpr_guarded_storage() noexcept : init_(false), storage_(trivial_init) {};
|
||||
|
||||
explicit constexpr constexpr_guarded_storage(const T& v) : init_(true), storage_(v) {}
|
||||
|
||||
explicit constexpr constexpr_guarded_storage(T&& v) : init_(true), storage_(move_(v)) {}
|
||||
|
||||
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)...) {}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void reset () noexcept { init_ = false; }
|
||||
|
||||
//~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
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
struct fallback_guarded_storage
|
||||
{
|
||||
bool init_;
|
||||
fallback_union_storage_t<T> storage_;
|
||||
|
||||
constexpr fallback_guarded_storage() noexcept : init_(false), storage_(trivial_init) {};
|
||||
|
||||
explicit constexpr fallback_guarded_storage(const T& v) : init_(true), storage_(v) {}
|
||||
|
||||
explicit constexpr fallback_guarded_storage(T&& v) : init_(true), storage_(move_(v)) {}
|
||||
|
||||
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)...) {}
|
||||
|
||||
void reset() noexcept
|
||||
{
|
||||
if (init_)
|
||||
{
|
||||
storage_.value_.T::~T();
|
||||
init_ = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
~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
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
using guarded_storage = typename ::std::conditional<
|
||||
::std::is_trivially_destructible<T>::value, // if possible
|
||||
constexpr_guarded_storage<typename ::std::remove_const<T>::type>, // use storage with trivial destructor
|
||||
fallback_guarded_storage<typename ::std::remove_const<T>::type>
|
||||
>::type;
|
||||
|
||||
|
||||
}}
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class T>
|
||||
class optional : public optional_detail::optional_tag
|
||||
{
|
||||
using storage_t = optional_detail::guarded_storage<T>;
|
||||
storage_t storage;
|
||||
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" );
|
||||
|
||||
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_; }
|
||||
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)
|
||||
{
|
||||
BOOST_ASSERT(!storage.init_);
|
||||
::new (static_cast<void*>(dataptr())) T(optional_detail::forward_<Args>(args)...);
|
||||
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;
|
||||
|
||||
using reference_type = T&;
|
||||
using reference_const_type = T const&;
|
||||
using argument_type = T const&;
|
||||
using rval_reference_type = T&&;
|
||||
using reference_type_of_temporary_wrapper = T&&;
|
||||
using pointer_type = T*;
|
||||
using pointer_const_type = T const*;
|
||||
|
||||
|
||||
constexpr bool is_initialized() const noexcept { return storage.init_; }
|
||||
|
||||
constexpr optional() noexcept : storage() {};
|
||||
constexpr optional(none_t) noexcept : storage() {};
|
||||
|
||||
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(conditional_storage_from_values(cond, v))
|
||||
{}
|
||||
|
||||
constexpr optional(bool cond, T&& v)
|
||||
: storage(conditional_storage_from_values(cond, optional_detail::move_(v)))
|
||||
{}
|
||||
|
||||
constexpr optional(const optional& rhs)
|
||||
: storage(conditional_storage_from_optional(rhs))
|
||||
{}
|
||||
|
||||
constexpr optional(optional&& rhs)
|
||||
noexcept(::std::is_nothrow_move_constructible<T>::value)
|
||||
: 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(conditional_storage_from_optional(rhs))
|
||||
{}
|
||||
|
||||
template <typename U, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U&&>)>
|
||||
constexpr explicit optional(optional<U> && rhs)
|
||||
: 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>)>
|
||||
/*non-constexpr (deprecated)*/
|
||||
explicit optional (FT&& factory)
|
||||
: storage()
|
||||
{
|
||||
factory.apply(this->dataptr());
|
||||
storage.init_ = true ;
|
||||
}
|
||||
|
||||
template <typename FT,
|
||||
BOOST_OPTIONAL_REQUIRES(optional_detail::is_in_place_factory<FT>)>
|
||||
/*non-constexpr (deprecated)*/
|
||||
explicit optional (FT&& factory)
|
||||
: storage()
|
||||
{
|
||||
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(!optional_detail::is_typed_in_place_factory<U>),
|
||||
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_in_place_factory<U>)>
|
||||
constexpr explicit optional(U&& v)
|
||||
: storage(optional_ns::in_place_init, optional_detail::forward_<U>(v))
|
||||
{}
|
||||
|
||||
template <typename... Args>
|
||||
constexpr explicit optional( in_place_init_t, Args&&... args )
|
||||
: storage(in_place_init, optional_detail::forward_<Args>(args)...)
|
||||
{}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR operator optional<T&>() & noexcept
|
||||
{
|
||||
return this->has_value() ? optional<T&>(**this) : optional<T&>();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
BOOST_OPTIONAL_CXX20_CONSTEXPR void reset(const T& v)
|
||||
{
|
||||
*this = v;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
BOOST_OPTIONAL_CXX20_CONSTEXPR void emplace(Args&&... args)
|
||||
{
|
||||
reset();
|
||||
// <-- now we are not containing a value
|
||||
initialize(optional_detail::forward_<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
BOOST_CXX14_CONSTEXPR optional& operator=(none_t) noexcept
|
||||
{
|
||||
reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
BOOST_OPTIONAL_CXX20_CONSTEXPR optional& operator=(const optional& rhs)
|
||||
{
|
||||
if (has_value())
|
||||
{
|
||||
if (rhs.has_value())
|
||||
**this = *rhs;
|
||||
else
|
||||
reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rhs.has_value())
|
||||
initialize(*rhs);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BOOST_OPTIONAL_CXX20_CONSTEXPR optional& operator=(optional&& rhs)
|
||||
noexcept(::std::is_nothrow_move_assignable<T>::value && ::std::is_nothrow_move_constructible<T>::value)
|
||||
{
|
||||
if (has_value())
|
||||
{
|
||||
if (rhs.has_value())
|
||||
**this = *optional_detail::move_(rhs);
|
||||
else
|
||||
reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rhs.has_value())
|
||||
initialize(*optional_detail::move_(rhs) );
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
BOOST_OPTIONAL_CXX20_CONSTEXPR optional& operator=(const optional<U>& rhs)
|
||||
{
|
||||
if (has_value())
|
||||
{
|
||||
if (rhs.has_value())
|
||||
**this = *rhs;
|
||||
else
|
||||
reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rhs.has_value())
|
||||
initialize(*rhs);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
BOOST_OPTIONAL_CXX20_CONSTEXPR optional& operator=(optional<U>&& rhs)
|
||||
{
|
||||
if (has_value())
|
||||
{
|
||||
if (rhs.has_value())
|
||||
**this = *optional_detail::move_(rhs);
|
||||
else
|
||||
reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rhs.has_value())
|
||||
initialize(*optional_detail::move_(rhs));
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class U = typename ::std::remove_cv<T>::type,
|
||||
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(!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)
|
||||
{
|
||||
if (is_initialized())
|
||||
contained_val() = optional_detail::forward_<U>(v);
|
||||
else
|
||||
initialize(optional_detail::forward_<U>(v));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class F, BOOST_OPTIONAL_REQUIRES(optional_detail::is_in_place_factory<F>)>
|
||||
/*non-constexpr (deprecated)*/
|
||||
optional& operator=(F&& factory)
|
||||
{
|
||||
reset();
|
||||
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();
|
||||
factory.apply(this->dataptr());
|
||||
storage.init_ = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
BOOST_OPTIONAL_CXX20_CONSTEXPR
|
||||
void swap(optional& rhs)
|
||||
noexcept(::std::is_nothrow_move_constructible<T>::value && noexcept(boost::core::invoke_swap(*rhs, *rhs)))
|
||||
{
|
||||
if (is_initialized())
|
||||
{
|
||||
if (rhs.is_initialized())
|
||||
boost::core::invoke_swap(contained_val(), rhs.contained_val());
|
||||
else
|
||||
{ rhs.initialize(optional_detail::move_(*this).contained_val()); reset(); }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rhs.is_initialized())
|
||||
{ initialize(optional_detail::move_(rhs).contained_val()); rhs.reset(); }
|
||||
}
|
||||
}
|
||||
|
||||
~optional() = default; // The destructor in `storage`, based on the specialization
|
||||
// will be trivial or not.
|
||||
|
||||
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 { 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; }
|
||||
|
||||
//BOOST_DEPRECATED("use `value_or(v)` instead")
|
||||
reference_type get_value_or (reference_type v) { return this->is_initialized() ? this->contained_val() : v; }
|
||||
|
||||
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(); }
|
||||
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 { 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&
|
||||
{
|
||||
return this->is_initialized() ? this->get() : (boost::throw_exception(boost::bad_optional_access()), this->get());
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR reference_type value() &
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return this->get();
|
||||
else
|
||||
boost::throw_exception(boost::bad_optional_access());
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR reference_type_of_temporary_wrapper value() &&
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return optional_detail::move_(this->get());
|
||||
else
|
||||
boost::throw_exception(boost::bad_optional_access());
|
||||
}
|
||||
|
||||
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&
|
||||
{
|
||||
return this->is_initialized() ? get() : T(optional_detail::forward_<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());
|
||||
else
|
||||
return optional_detail::forward_<U>(v);
|
||||
}
|
||||
|
||||
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&
|
||||
{
|
||||
return this->is_initialized() ? get() : value_type(f());
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
BOOST_CXX14_CONSTEXPR value_type value_or_eval ( F f ) &&
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return optional_detail::move_(get());
|
||||
else
|
||||
return f();
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
BOOST_CXX14_CONSTEXPR optional<typename optional_detail::result_of<F, reference_type>::type>
|
||||
map(F f) &
|
||||
{
|
||||
if (this->has_value())
|
||||
return f(get());
|
||||
else
|
||||
return none;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
constexpr optional<typename optional_detail::result_of<F, reference_const_type>::type>
|
||||
map(F f) const&
|
||||
{
|
||||
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_of<F, reference_type_of_temporary_wrapper>::type>
|
||||
map(F f) &&
|
||||
{
|
||||
if (this->has_value())
|
||||
return f(optional_detail::move_(this->get()));
|
||||
else
|
||||
return none;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
BOOST_CXX14_CONSTEXPR optional<typename optional_detail::result_value_type<F, reference_type>::type>
|
||||
flat_map(F f) &
|
||||
{
|
||||
if (this->has_value())
|
||||
return f(get());
|
||||
else
|
||||
return none;
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
constexpr optional<typename optional_detail::result_value_type<F, reference_const_type>::type>
|
||||
flat_map(F f) const&
|
||||
{
|
||||
return this->has_value() ?
|
||||
f(get()) :
|
||||
optional<typename optional_detail::result_value_type<F, reference_const_type>::type>();
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
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())
|
||||
return f(optional_detail::move_(get()));
|
||||
else
|
||||
return none;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename 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)))
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // BOOST_OPTIONAL_DETAIL_UNION_OPTIONAL_01FEB2026_HPP
|
||||
+101
-228
@@ -1,5 +1,5 @@
|
||||
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
|
||||
// Copyright (C) 2014 - 2021 Andrzej Krzemienski.
|
||||
// Copyright (C) 2014 - 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
|
||||
@@ -7,23 +7,56 @@
|
||||
//
|
||||
// See http://www.boost.org/libs/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// You are welcome to contact the authors at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
// akrzemi1@gmail.com
|
||||
//
|
||||
// You can file a GitHub issue at:
|
||||
// https://github.com/boostorg/optional/issues
|
||||
//
|
||||
// Revisions:
|
||||
// 27 Apr 2008 (improved swap) Fernando Cacciola, Niels Dekker, Thorsten Ottosen
|
||||
// 05 May 2014 (Added move semantics) Andrzej Krzemienski
|
||||
// 01 Feb 2026 Added constexpr implementaiton for C++14
|
||||
//
|
||||
#ifndef BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
|
||||
#define BOOST_OPTIONAL_OPTIONAL_FLC_19NOV2002_HPP
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <boost/optional/detail/optional_select_implementation.hpp>
|
||||
#include <boost/optional/detail/optional_common_defs.hpp>
|
||||
|
||||
|
||||
#ifndef BOOST_NO_IOSTREAM
|
||||
#include <iosfwd>
|
||||
|
||||
namespace boost {
|
||||
|
||||
// The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header.
|
||||
template<class CharType, class CharTrait>
|
||||
std::basic_ostream<CharType, CharTrait>&
|
||||
operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optional_tag const&)
|
||||
{
|
||||
static_assert(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>");
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
#endif // BOOST_NO_IOSTREAM
|
||||
|
||||
|
||||
#include <boost/none.hpp>
|
||||
|
||||
|
||||
#if defined BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
#include <boost/optional/detail/union_optional.hpp>
|
||||
#else
|
||||
|
||||
|
||||
#include <new>
|
||||
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/core/addressof.hpp>
|
||||
#include <boost/core/enable_if.hpp>
|
||||
#include <boost/core/invoke_swap.hpp>
|
||||
#include <boost/core/launder.hpp>
|
||||
@@ -50,83 +83,18 @@
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_volatile.hpp>
|
||||
#include <boost/type_traits/is_scalar.hpp>
|
||||
#include <boost/none.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>
|
||||
#include <boost/optional/detail/optional_hash.hpp>
|
||||
#include <boost/optional/detail/optional_utility.hpp>
|
||||
|
||||
namespace boost { namespace optional_detail {
|
||||
|
||||
template <typename T>
|
||||
struct optional_value_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename U>
|
||||
struct optional_value_type< ::boost::optional<U> >
|
||||
{
|
||||
typedef U type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
T declval();
|
||||
|
||||
|
||||
// implementing my own result_of so that it works for C++11 (std::result_of)
|
||||
// and in C++20 (std::invoke_result).
|
||||
template <typename F, typename Ref, typename Rslt = decltype(declval<F>()(declval<Ref>()))>
|
||||
struct result_of
|
||||
{
|
||||
typedef Rslt type;
|
||||
};
|
||||
|
||||
template <typename F, typename Ref, typename Rslt = typename optional_value_type<typename result_of<F, Ref>::type>::type>
|
||||
struct result_value_type
|
||||
{
|
||||
typedef Rslt type;
|
||||
};
|
||||
|
||||
// optional<typename optional_detail::optional_value_type<decltype(optional_detail::declval<F>()(optional_detail::declval<reference_type>()))>::type>
|
||||
|
||||
}} // namespace boost::optional_detail
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace optional_ns {
|
||||
|
||||
// a tag for in-place initialization of contained value
|
||||
struct in_place_init_t
|
||||
{
|
||||
struct init_tag{};
|
||||
BOOST_CONSTEXPR explicit in_place_init_t(init_tag){}
|
||||
};
|
||||
BOOST_INLINE_CONSTEXPR in_place_init_t in_place_init ((in_place_init_t::init_tag()));
|
||||
|
||||
// a tag for conditional in-place initialization of contained value
|
||||
struct in_place_init_if_t
|
||||
{
|
||||
struct init_tag{};
|
||||
BOOST_CONSTEXPR explicit in_place_init_if_t(init_tag){}
|
||||
};
|
||||
BOOST_INLINE_CONSTEXPR in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag()));
|
||||
|
||||
} // namespace optional_ns
|
||||
|
||||
using optional_ns::in_place_init_t;
|
||||
using optional_ns::in_place_init;
|
||||
using optional_ns::in_place_init_if_t;
|
||||
using optional_ns::in_place_init_if;
|
||||
|
||||
namespace optional_detail {
|
||||
|
||||
struct init_value_tag {};
|
||||
|
||||
struct optional_tag {};
|
||||
|
||||
|
||||
template<class T>
|
||||
class optional_base : public optional_tag
|
||||
@@ -177,7 +145,7 @@ class optional_base : public optional_tag
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
construct( optional_detail::move(val) );
|
||||
construct( optional_detail::move_(val) );
|
||||
}
|
||||
|
||||
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional<T>.
|
||||
@@ -197,7 +165,7 @@ class optional_base : public optional_tag
|
||||
m_initialized(false)
|
||||
{
|
||||
if ( cond )
|
||||
construct(optional_detail::move(val));
|
||||
construct(optional_detail::move_(val));
|
||||
}
|
||||
|
||||
// Creates a deep copy of another optional<T>
|
||||
@@ -218,7 +186,7 @@ class optional_base : public optional_tag
|
||||
m_initialized(false)
|
||||
{
|
||||
if ( rhs.is_initialized() )
|
||||
construct( optional_detail::move(rhs.get_impl()) );
|
||||
construct( optional_detail::move_(rhs.get_impl()) );
|
||||
}
|
||||
|
||||
|
||||
@@ -227,7 +195,7 @@ class optional_base : public optional_tag
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
construct(optional_detail::forward<Expr>(expr),tag);
|
||||
construct(optional_detail::forward_<Expr>(expr),tag);
|
||||
}
|
||||
|
||||
optional_base& operator= ( optional_base const& rhs )
|
||||
@@ -268,13 +236,13 @@ class optional_base : public optional_tag
|
||||
if (is_initialized())
|
||||
{
|
||||
if ( rhs.is_initialized() )
|
||||
assign_value( optional_detail::move(rhs.get_impl()) );
|
||||
assign_value( optional_detail::move_(rhs.get_impl()) );
|
||||
else destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( rhs.is_initialized() )
|
||||
construct(optional_detail::move(rhs.get_impl()));
|
||||
construct(optional_detail::move_(rhs.get_impl()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,8 +302,8 @@ class optional_base : public optional_tag
|
||||
void assign ( rval_reference_type val )
|
||||
{
|
||||
if (is_initialized())
|
||||
assign_value( optional_detail::move(val) );
|
||||
else construct( optional_detail::move(val) );
|
||||
assign_value( optional_detail::move_(val) );
|
||||
else construct( optional_detail::move_(val) );
|
||||
}
|
||||
|
||||
// Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
|
||||
@@ -348,8 +316,8 @@ class optional_base : public optional_tag
|
||||
void assign_expr ( Expr&& expr, ExprPtr const* tag )
|
||||
{
|
||||
if (is_initialized())
|
||||
assign_expr_to_initialized(optional_detail::forward<Expr>(expr),tag);
|
||||
else construct(optional_detail::forward<Expr>(expr),tag);
|
||||
assign_expr_to_initialized(optional_detail::forward_<Expr>(expr),tag);
|
||||
else construct(optional_detail::forward_<Expr>(expr),tag);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -381,7 +349,7 @@ class optional_base : public optional_tag
|
||||
|
||||
void construct ( rval_reference_type val )
|
||||
{
|
||||
::new (m_storage.address()) unqualified_value_type( optional_detail::move(val) ) ;
|
||||
::new (m_storage.address()) unqualified_value_type( optional_detail::move_(val) ) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
@@ -391,7 +359,7 @@ class optional_base : public optional_tag
|
||||
template<class... Args>
|
||||
void construct ( in_place_init_t, Args&&... args )
|
||||
{
|
||||
::new (m_storage.address()) unqualified_value_type( optional_detail::forward<Args>(args)... ) ;
|
||||
::new (m_storage.address()) unqualified_value_type( optional_detail::forward_<Args>(args)... ) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
@@ -399,7 +367,7 @@ class optional_base : public optional_tag
|
||||
void emplace_assign ( Args&&... args )
|
||||
{
|
||||
destroy();
|
||||
construct(in_place_init, optional_detail::forward<Args>(args)...);
|
||||
construct(in_place_init, optional_detail::forward_<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
@@ -407,7 +375,7 @@ class optional_base : public optional_tag
|
||||
:
|
||||
m_initialized(false)
|
||||
{
|
||||
construct(in_place_init, optional_detail::forward<Args>(args)...);
|
||||
construct(in_place_init, optional_detail::forward_<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
@@ -416,7 +384,7 @@ class optional_base : public optional_tag
|
||||
m_initialized(false)
|
||||
{
|
||||
if ( cond )
|
||||
construct(in_place_init, optional_detail::forward<Args>(args)...);
|
||||
construct(in_place_init, optional_detail::forward_<Args>(args)...);
|
||||
}
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
@@ -461,7 +429,7 @@ class optional_base : public optional_tag
|
||||
template<class Expr>
|
||||
void construct ( Expr&& expr, void const* )
|
||||
{
|
||||
new (m_storage.address()) unqualified_value_type(optional_detail::forward<Expr>(expr)) ;
|
||||
new (m_storage.address()) unqualified_value_type(optional_detail::forward_<Expr>(expr)) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
|
||||
@@ -472,7 +440,7 @@ class optional_base : public optional_tag
|
||||
template<class Expr>
|
||||
void assign_expr_to_initialized ( Expr&& expr, void const* )
|
||||
{
|
||||
assign_value( optional_detail::forward<Expr>(expr) );
|
||||
assign_value( optional_detail::forward_<Expr>(expr) );
|
||||
}
|
||||
|
||||
#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
|
||||
@@ -497,7 +465,7 @@ class optional_base : public optional_tag
|
||||
{
|
||||
// An exception can be thrown here.
|
||||
// It it happens, THIS will be left uninitialized.
|
||||
new (m_storage.address()) unqualified_value_type(optional_detail::move(expr.get())) ;
|
||||
new (m_storage.address()) unqualified_value_type(optional_detail::move_(expr.get())) ;
|
||||
m_initialized = true ;
|
||||
}
|
||||
}
|
||||
@@ -548,16 +516,15 @@ struct has_dedicated_constructor
|
||||
{};
|
||||
|
||||
template <typename U>
|
||||
struct is_in_place_factory
|
||||
: boost::disjunction< boost::is_base_of<boost::in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>,
|
||||
boost::is_base_of<boost::typed_in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type> >
|
||||
struct is_factory
|
||||
: boost::disjunction< is_in_place_factory<U>, is_typed_in_place_factory<U> >
|
||||
{};
|
||||
|
||||
#if !defined(BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT)
|
||||
|
||||
template <typename T, typename U>
|
||||
struct is_factory_or_constructible_to_T
|
||||
: boost::disjunction< is_in_place_factory<U>, boost::is_constructible<T, U&&> >
|
||||
: boost::disjunction< is_factory<U>, boost::is_constructible<T, U&&> >
|
||||
{};
|
||||
|
||||
template <typename T, typename U>
|
||||
@@ -597,7 +564,7 @@ struct is_opt_assignable : boost::is_convertible<U, T>
|
||||
|
||||
template <typename T, typename U>
|
||||
struct is_factory_or_opt_assignable_to_T
|
||||
: boost::disjunction< is_in_place_factory<U>, is_opt_assignable<T, U> >
|
||||
: boost::disjunction< is_factory<U>, is_opt_assignable<T, U> >
|
||||
{};
|
||||
|
||||
template <typename T, typename U, bool = has_dedicated_constructor<T, U>::value>
|
||||
@@ -675,7 +642,7 @@ class optional
|
||||
|
||||
// Creates an optional<T> initialized with 'move(val)'.
|
||||
// Can throw if T::T(T &&) does
|
||||
optional ( rval_reference_type val ) : base(optional_detail::init_value_tag(), optional_detail::forward<T>(val))
|
||||
optional ( rval_reference_type val ) : base(optional_detail::init_value_tag(), optional_detail::forward_<T>(val))
|
||||
{}
|
||||
|
||||
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
|
||||
@@ -684,7 +651,7 @@ class optional
|
||||
|
||||
/// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
|
||||
// Can throw if T::T(T &&) does
|
||||
optional ( bool cond, rval_reference_type val ) : base( cond, optional_detail::forward<T>(val) )
|
||||
optional ( bool cond, rval_reference_type val ) : base( cond, optional_detail::forward_<T>(val) )
|
||||
{}
|
||||
|
||||
// NOTE: MSVC needs templated versions first
|
||||
@@ -718,7 +685,7 @@ class optional
|
||||
base()
|
||||
{
|
||||
if ( rhs.is_initialized() )
|
||||
this->construct( optional_detail::move(rhs.get()) );
|
||||
this->construct( optional_detail::move_(rhs.get()) );
|
||||
}
|
||||
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
@@ -737,7 +704,7 @@ class optional
|
||||
explicit optional ( Expr&& expr,
|
||||
BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate<T, Expr>, bool>::type = true
|
||||
)
|
||||
: base(optional_detail::forward<Expr>(expr),boost::addressof(expr))
|
||||
: base(optional_detail::forward_<Expr>(expr),boost::addressof(expr))
|
||||
{}
|
||||
|
||||
#endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
@@ -757,7 +724,7 @@ class optional
|
||||
#else
|
||||
optional ( optional && rhs )
|
||||
BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
|
||||
: base( optional_detail::move(rhs) )
|
||||
: base( optional_detail::move_(rhs) )
|
||||
{}
|
||||
#endif
|
||||
|
||||
@@ -776,7 +743,7 @@ class optional
|
||||
BOOST_DEDUCED_TYPENAME boost::enable_if<optional_detail::is_optional_val_assign_candidate<T, Expr>, optional&>::type
|
||||
operator= ( Expr&& expr )
|
||||
{
|
||||
this->assign_expr(optional_detail::forward<Expr>(expr),boost::addressof(expr));
|
||||
this->assign_expr(optional_detail::forward_<Expr>(expr),boost::addressof(expr));
|
||||
return *this ;
|
||||
}
|
||||
|
||||
@@ -798,7 +765,7 @@ class optional
|
||||
template<class U>
|
||||
optional& operator= ( optional<U> && rhs )
|
||||
{
|
||||
this->assign(optional_detail::move(rhs));
|
||||
this->assign(optional_detail::move_(rhs));
|
||||
return *this ;
|
||||
}
|
||||
|
||||
@@ -834,7 +801,7 @@ class optional
|
||||
BOOST_DEDUCED_TYPENAME boost::enable_if<boost::is_same<T, BOOST_DEDUCED_TYPENAME boost::decay<T_>::type>, optional&>::type
|
||||
operator= ( T_&& val )
|
||||
{
|
||||
this->assign( optional_detail::forward<T_>(val) ) ;
|
||||
this->assign( optional_detail::forward_<T_>(val) ) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
@@ -851,7 +818,7 @@ class optional
|
||||
// Assigns from a T (deep-moves the rhs value)
|
||||
optional& operator= ( rval_reference_type val )
|
||||
{
|
||||
this->assign( optional_detail::move(val) ) ;
|
||||
this->assign( optional_detail::move_(val) ) ;
|
||||
return *this ;
|
||||
}
|
||||
|
||||
@@ -871,17 +838,17 @@ class optional
|
||||
template<class... Args>
|
||||
void emplace ( Args&&... args )
|
||||
{
|
||||
this->emplace_assign( optional_detail::forward<Args>(args)... );
|
||||
this->emplace_assign( optional_detail::forward_<Args>(args)... );
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
explicit optional ( in_place_init_t, Args&&... args )
|
||||
: base( in_place_init, optional_detail::forward<Args>(args)... )
|
||||
: base( in_place_init, optional_detail::forward_<Args>(args)... )
|
||||
{}
|
||||
|
||||
template<class... Args>
|
||||
explicit optional ( in_place_init_if_t, bool cond, Args&&... args )
|
||||
: base( in_place_init_if, cond, optional_detail::forward<Args>(args)... )
|
||||
: base( in_place_init_if, cond, optional_detail::forward_<Args>(args)... )
|
||||
{}
|
||||
|
||||
void swap( optional & arg )
|
||||
@@ -915,7 +882,7 @@ class optional
|
||||
reference_type operator *() BOOST_OPTIONAL_REF_QUAL { return this->get() ; }
|
||||
|
||||
#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
|
||||
reference_type_of_temporary_wrapper operator *() && { return optional_detail::move(this->get()) ; }
|
||||
reference_type_of_temporary_wrapper operator *() && { return optional_detail::move_(this->get()) ; }
|
||||
#endif
|
||||
|
||||
reference_const_type value() BOOST_OPTIONAL_CONST_REF_QUAL
|
||||
@@ -940,7 +907,7 @@ class optional
|
||||
if (this->is_initialized())
|
||||
return get();
|
||||
else
|
||||
return optional_detail::forward<U>(v);
|
||||
return optional_detail::forward_<U>(v);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
@@ -956,7 +923,7 @@ class optional
|
||||
reference_type_of_temporary_wrapper value() &&
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return optional_detail::move(this->get()) ;
|
||||
return optional_detail::move_(this->get()) ;
|
||||
else
|
||||
throw_exception(bad_optional_access());
|
||||
}
|
||||
@@ -965,16 +932,16 @@ class optional
|
||||
value_type value_or ( U&& v ) &&
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return optional_detail::move(get());
|
||||
return optional_detail::move_(get());
|
||||
else
|
||||
return optional_detail::forward<U>(v);
|
||||
return optional_detail::forward_<U>(v);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
value_type value_or_eval ( F f ) &&
|
||||
{
|
||||
if (this->is_initialized())
|
||||
return optional_detail::move(get());
|
||||
return optional_detail::move_(get());
|
||||
else
|
||||
return f();
|
||||
}
|
||||
@@ -1005,7 +972,7 @@ class optional
|
||||
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()));
|
||||
return f(optional_detail::move_(this->get()));
|
||||
else
|
||||
return none;
|
||||
}
|
||||
@@ -1037,7 +1004,7 @@ class optional
|
||||
flat_map(F f) &&
|
||||
{
|
||||
if (this->has_value())
|
||||
return f(optional_detail::move(get()));
|
||||
return f(optional_detail::move_(get()));
|
||||
else
|
||||
return none;
|
||||
}
|
||||
@@ -1048,128 +1015,34 @@ class optional
|
||||
explicit operator bool() const BOOST_NOEXCEPT { return this->has_value() ; }
|
||||
} ;
|
||||
|
||||
|
||||
template<class T>
|
||||
class optional<T&&>
|
||||
{
|
||||
static_assert(sizeof(T) == 0, "Optional rvalue references are illegal.");
|
||||
} ;
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <boost/optional/detail/optional_swap.hpp>
|
||||
|
||||
#endif // pre-C++14 impl
|
||||
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <class T>
|
||||
class optional<T&&>
|
||||
{
|
||||
static_assert(sizeof(T) == 0, "Optional rvalue references are illegal.");
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS
|
||||
# include <boost/optional/detail/optional_reference_spec.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type> make_optional ( T && v )
|
||||
{
|
||||
return optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>(optional_detail::forward<T>(v));
|
||||
}
|
||||
|
||||
// Returns optional<T>(cond,v)
|
||||
template<class T>
|
||||
inline
|
||||
optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type> make_optional ( bool cond, T && v )
|
||||
{
|
||||
return optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>(cond,optional_detail::forward<T>(v));
|
||||
}
|
||||
|
||||
|
||||
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
|
||||
// No-throw
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
|
||||
get ( optional<T> const& opt )
|
||||
{
|
||||
return opt.get() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
|
||||
get ( optional<T>& opt )
|
||||
{
|
||||
return opt.get() ;
|
||||
}
|
||||
|
||||
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
|
||||
// No-throw
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
|
||||
get ( optional<T> const* opt )
|
||||
{
|
||||
return opt->get_ptr() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
|
||||
get ( optional<T>* opt )
|
||||
{
|
||||
return opt->get_ptr() ;
|
||||
}
|
||||
|
||||
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
|
||||
// No-throw
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
|
||||
get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
|
||||
{
|
||||
return opt.get_value_or(v) ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
|
||||
get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
|
||||
{
|
||||
return opt.get_value_or(v) ;
|
||||
}
|
||||
|
||||
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
|
||||
// No-throw
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
|
||||
get_pointer ( optional<T> const& opt )
|
||||
{
|
||||
return opt.get_ptr() ;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline
|
||||
BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
|
||||
get_pointer ( optional<T>& opt )
|
||||
{
|
||||
return opt.get_ptr() ;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#ifndef BOOST_NO_IOSTREAM
|
||||
namespace boost {
|
||||
|
||||
// The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header.
|
||||
template<class CharType, class CharTrait>
|
||||
std::basic_ostream<CharType, CharTrait>&
|
||||
operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optional_tag const&)
|
||||
{
|
||||
static_assert(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>");
|
||||
return os;
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
#endif // BOOST_NO_IOSTREAM
|
||||
|
||||
#include <boost/optional/detail/optional_hash.hpp>
|
||||
#include <boost/optional/detail/optional_relops.hpp>
|
||||
#include <boost/optional/detail/optional_swap.hpp>
|
||||
#include <boost/optional/detail/optional_nonmember_interface.hpp>
|
||||
|
||||
|
||||
#endif // header guard
|
||||
|
||||
@@ -17,25 +17,35 @@
|
||||
#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
|
||||
template<class T> 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_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> void swap ( optional<T&>& , optional<T&>& ) BOOST_NOEXCEPT;
|
||||
template<class T> BOOST_CXX14_CONSTEXPR void swap ( optional<T&>& , optional<T&>& ) BOOST_NOEXCEPT;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ operator>>(std::basic_istream<CharType, CharTrait>& in, optional<T>& v)
|
||||
{
|
||||
T x;
|
||||
in >> x;
|
||||
v = optional_detail::move(x);
|
||||
v = optional_detail::move_(x);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+4
-1
@@ -28,7 +28,6 @@ project
|
||||
cxx11_explicit_conversion_operators
|
||||
# cxx11_noexcept
|
||||
cxx11_rvalue_references
|
||||
cxx11_static_assert
|
||||
cxx11_variadic_templates
|
||||
]
|
||||
;
|
||||
@@ -37,7 +36,9 @@ project
|
||||
run optional_test.cpp : : : <library>/boost/bind//boost_bind ;
|
||||
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_convert_from_T.cpp ;
|
||||
run optional_test_convert_assign.cpp ;
|
||||
@@ -47,6 +48,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 ;
|
||||
@@ -78,6 +80,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>());
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
// 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/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
#ifdef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
|
||||
struct Record
|
||||
{
|
||||
int i;
|
||||
constexpr explicit Record(int i) : i(i) {}
|
||||
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, "");
|
||||
|
||||
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 bool test_reset() {
|
||||
boost::optional<int> o = 1;
|
||||
assert(o);
|
||||
o = boost::none;
|
||||
assert(!o);
|
||||
return o == boost::none;
|
||||
}
|
||||
|
||||
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> 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, "");
|
||||
}
|
||||
|
||||
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, "");
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include "boost/none.hpp"
|
||||
#include "boost/type_traits/is_assignable.hpp"
|
||||
|
||||
//#ifndef BOOST_OPTIONAL_NO_CONVERTING_COPY_CTOR
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
+36
-36
@@ -75,13 +75,13 @@ void test_move_ctor_from_U()
|
||||
optional<Oracle> o1 ((OracleVal()));
|
||||
BOOST_TEST(o1);
|
||||
BOOST_TEST(o1->s == sValueMoveConstructed || o1->s == sMoveConstructed);
|
||||
|
||||
|
||||
OracleVal v1;
|
||||
optional<Oracle> o2 (v1);
|
||||
BOOST_TEST(o2);
|
||||
BOOST_TEST(o2->s == sValueCopyConstructed || o2->s == sCopyConstructed || o2->s == sMoveConstructed );
|
||||
BOOST_TEST(v1.s == sIntConstructed);
|
||||
|
||||
|
||||
optional<Oracle> o3 (std::move(v1));
|
||||
BOOST_TEST(o3);
|
||||
BOOST_TEST(o3->s == sValueMoveConstructed || o3->s == sMoveConstructed);
|
||||
@@ -93,13 +93,13 @@ void test_move_ctor_form_T()
|
||||
optional<Oracle> o1 ((Oracle()));
|
||||
BOOST_TEST(o1);
|
||||
BOOST_TEST(o1->s == sMoveConstructed);
|
||||
|
||||
|
||||
Oracle v1;
|
||||
optional<Oracle> o2 (v1);
|
||||
BOOST_TEST(o2);
|
||||
BOOST_TEST(o2->s == sCopyConstructed);
|
||||
BOOST_TEST(v1.s == sDefaultConstructed);
|
||||
|
||||
|
||||
optional<Oracle> o3 (std::move(v1));
|
||||
BOOST_TEST(o3);
|
||||
BOOST_TEST(o3->s == sMoveConstructed);
|
||||
@@ -110,24 +110,24 @@ void test_move_ctor_from_optional_T()
|
||||
{
|
||||
optional<Oracle> o1;
|
||||
optional<Oracle> o2(std::move(o1));
|
||||
|
||||
|
||||
BOOST_TEST(!o1);
|
||||
BOOST_TEST(!o2);
|
||||
|
||||
|
||||
optional<Oracle> o3((Oracle()));
|
||||
optional<Oracle> o4(std::move(o3));
|
||||
BOOST_TEST(o3);
|
||||
BOOST_TEST(o4);
|
||||
BOOST_TEST(o3->s == sMovedFrom);
|
||||
BOOST_TEST(o4->s == sMoveConstructed);
|
||||
|
||||
|
||||
optional<Oracle> o5((optional<Oracle>()));
|
||||
BOOST_TEST(!o5);
|
||||
|
||||
|
||||
optional<Oracle> o6((optional<Oracle>(Oracle())));
|
||||
BOOST_TEST(o6);
|
||||
BOOST_TEST(o6->s == sMoveConstructed);
|
||||
|
||||
|
||||
optional<Oracle> o7(o6); // does copy ctor from non-const lvalue compile?
|
||||
}
|
||||
|
||||
@@ -137,13 +137,13 @@ void test_move_assign_from_U()
|
||||
o1 = boost::none; // test if additional assignments didn't break it
|
||||
o1 = OracleVal();
|
||||
BOOST_TEST(o1);
|
||||
|
||||
BOOST_TEST(o1->s == sValueMoveConstructed);
|
||||
|
||||
|
||||
BOOST_TEST(o1->s == sValueMoveConstructed);
|
||||
|
||||
o1 = OracleVal();
|
||||
BOOST_TEST(o1);
|
||||
BOOST_TEST(o1->s == sMoveAssigned);
|
||||
|
||||
BOOST_TEST(o1->s == sMoveAssigned || o1->s == sValueMoveAssigned);
|
||||
|
||||
OracleVal v1;
|
||||
optional<Oracle> o2;
|
||||
o2 = v1;
|
||||
@@ -152,9 +152,9 @@ void test_move_assign_from_U()
|
||||
BOOST_TEST(v1.s == sIntConstructed);
|
||||
o2 = v1;
|
||||
BOOST_TEST(o2);
|
||||
BOOST_TEST(o2->s == sCopyAssigned || o2->s == sMoveAssigned);
|
||||
BOOST_TEST(o2->s == sCopyAssigned || o2->s == sMoveAssigned || o2->s == sValueCopyAssigned);
|
||||
BOOST_TEST(v1.s == sIntConstructed);
|
||||
|
||||
|
||||
optional<Oracle> o3;
|
||||
o3 = std::move(v1);
|
||||
BOOST_TEST(o3);
|
||||
@@ -167,12 +167,12 @@ void test_move_assign_from_T()
|
||||
optional<Oracle> o1;
|
||||
o1 = Oracle();
|
||||
BOOST_TEST(o1);
|
||||
BOOST_TEST(o1->s == sMoveConstructed);
|
||||
|
||||
BOOST_TEST(o1->s == sMoveConstructed);
|
||||
|
||||
o1 = Oracle();
|
||||
BOOST_TEST(o1);
|
||||
BOOST_TEST(o1->s == sMoveAssigned);
|
||||
|
||||
BOOST_TEST(o1->s == sMoveAssigned);
|
||||
|
||||
Oracle v1;
|
||||
optional<Oracle> o2;
|
||||
o2 = v1;
|
||||
@@ -183,7 +183,7 @@ void test_move_assign_from_T()
|
||||
BOOST_TEST(o2);
|
||||
BOOST_TEST(o2->s == sCopyAssigned);
|
||||
BOOST_TEST(v1.s == sDefaultConstructed);
|
||||
|
||||
|
||||
optional<Oracle> o3;
|
||||
o3 = std::move(v1);
|
||||
BOOST_TEST(o3);
|
||||
@@ -203,13 +203,13 @@ void test_move_assign_from_optional_T()
|
||||
BOOST_TEST(o3->s == sMoveConstructed);
|
||||
BOOST_TEST(o1);
|
||||
BOOST_TEST(o1->s == sCopyConstructed);
|
||||
|
||||
|
||||
o2 = std::move(o3);
|
||||
BOOST_TEST(o3);
|
||||
BOOST_TEST(o3->s == sMovedFrom);
|
||||
BOOST_TEST(o2);
|
||||
BOOST_TEST(o2->s == sMoveConstructed);
|
||||
|
||||
|
||||
o2 = optional<Oracle>((Oracle()));
|
||||
BOOST_TEST(o2);
|
||||
BOOST_TEST(o2->s == sMoveAssigned);
|
||||
@@ -222,11 +222,11 @@ public:
|
||||
MoveOnly(int v) : val(v) {}
|
||||
MoveOnly(MoveOnly&& rhs) : val(rhs.val) { rhs.val = 0; }
|
||||
void operator=(MoveOnly&& rhs) {val = rhs.val; rhs.val = 0; }
|
||||
|
||||
|
||||
private:
|
||||
MoveOnly(MoveOnly const&);
|
||||
void operator=(MoveOnly const&);
|
||||
|
||||
|
||||
friend class MoveOnlyB;
|
||||
};
|
||||
|
||||
@@ -243,7 +243,7 @@ void test_with_move_only()
|
||||
BOOST_TEST(o4->val == 1);
|
||||
BOOST_TEST(o2);
|
||||
BOOST_TEST(o2->val == 0);
|
||||
|
||||
|
||||
o3 = std::move(o4);
|
||||
BOOST_TEST(o3);
|
||||
BOOST_TEST(o3->val == 1);
|
||||
@@ -260,7 +260,7 @@ public:
|
||||
void operator=(MoveOnlyB&& rhs) {val = rhs.val; rhs.val = 0; }
|
||||
MoveOnlyB(MoveOnly&& rhs) : val(rhs.val) { rhs.val = 0; }
|
||||
void operator=(MoveOnly&& rhs) {val = rhs.val; rhs.val = 0; }
|
||||
|
||||
|
||||
private:
|
||||
MoveOnlyB(MoveOnlyB const&);
|
||||
void operator=(MoveOnlyB const&);
|
||||
@@ -273,14 +273,14 @@ void test_move_assign_from_optional_U()
|
||||
optional<MoveOnly> a((MoveOnly(2)));
|
||||
optional<MoveOnlyB> b1;
|
||||
b1 = std::move(a);
|
||||
|
||||
|
||||
BOOST_TEST(b1);
|
||||
BOOST_TEST(b1->val == 2);
|
||||
BOOST_TEST(a);
|
||||
BOOST_TEST(a->val == 0);
|
||||
|
||||
|
||||
b1 = MoveOnly(4);
|
||||
|
||||
|
||||
BOOST_TEST(b1);
|
||||
BOOST_TEST(b1->val == 4);
|
||||
}
|
||||
@@ -289,14 +289,14 @@ void test_move_ctor_from_optional_U()
|
||||
{
|
||||
optional<MoveOnly> a((MoveOnly(2)));
|
||||
optional<MoveOnlyB> b1(std::move(a));
|
||||
|
||||
|
||||
BOOST_TEST(b1);
|
||||
BOOST_TEST(b1->val == 2);
|
||||
BOOST_TEST(a);
|
||||
BOOST_TEST(a->val == 0);
|
||||
|
||||
|
||||
optional<MoveOnlyB> b2(( optional<MoveOnly>(( MoveOnly(4) )) ));
|
||||
|
||||
|
||||
BOOST_TEST(b2);
|
||||
BOOST_TEST(b2->val == 4);
|
||||
}
|
||||
@@ -306,7 +306,7 @@ void test_swap()
|
||||
optional<MoveOnly> a((MoveOnly(2)));
|
||||
optional<MoveOnly> b((MoveOnly(3)));
|
||||
swap(a, b);
|
||||
|
||||
|
||||
BOOST_TEST(a->val == 3);
|
||||
BOOST_TEST(b->val == 2);
|
||||
}
|
||||
@@ -317,12 +317,12 @@ void test_optional_ref_to_movables()
|
||||
optional<MoveOnly&> orm = m;
|
||||
orm->val = 2;
|
||||
BOOST_TEST(m.val == 2);
|
||||
|
||||
|
||||
optional<MoveOnly&> orm2 = orm;
|
||||
orm2->val = 1;
|
||||
BOOST_TEST(m.val == 1);
|
||||
BOOST_TEST(orm->val == 1);
|
||||
|
||||
|
||||
optional<MoveOnly&> orm3 = std::move(orm);
|
||||
orm3->val = 4;
|
||||
BOOST_TEST(m.val == 4);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#include "boost/core/enable_if.hpp"
|
||||
#include "boost/type_traits/is_constructible.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
#pragma hdrstop
|
||||
#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();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2014 Andrzej Krzemienski.
|
||||
// Copyright (C) 2014, 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
|
||||
@@ -9,6 +9,7 @@
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include <boost/type_traits/is_constructible.hpp>
|
||||
#include "boost/optional/optional.hpp"
|
||||
|
||||
#ifdef BOOST_BORLANDC
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "boost/type_traits/is_base_of.hpp"
|
||||
#include "boost/optional/detail/experimental_traits.hpp"
|
||||
|
||||
#ifndef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
|
||||
|
||||
struct PrivDefault
|
||||
@@ -135,12 +136,15 @@ void test_trivial_copyability()
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
|
||||
int main()
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
#ifndef BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS
|
||||
test_type_traits();
|
||||
test_trivial_copyability();
|
||||
#endif
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -210,6 +210,7 @@ namespace boost {
|
||||
// Compile time tweaking on whether or not swap should use the default constructor:
|
||||
//
|
||||
|
||||
#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 {} ;
|
||||
|
||||
@@ -218,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_UNION_IMPLEMENTATION
|
||||
|
||||
//
|
||||
// Specialization of boost::swap:
|
||||
@@ -352,15 +353,19 @@ 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_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::class_whose_explicit_ctor_should_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_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) ) );
|
||||
( test_swap_member_function( ARG(optional_swap_test::class_whose_explicit_ctor_should_be_used) ) );
|
||||
( test_swap_member_function( ARG(optional_swap_test::template_whose_default_ctor_should_be_used<char>) ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
int main()
|
||||
|
||||
Reference in New Issue
Block a user