Compare commits

..

11 Commits

Author SHA1 Message Date
Andrzej Krzemienski f564e11dea add robust constexpr support 2026-02-08 11:27:30 +01:00
Andrzej Krzemienski b6a57cdb46 docs: fixed release notes 2026-02-07 23:05:25 +01:00
Andrzej Krzemienski dd0e9d8a72 temporarily disable the constexpr implementation 2026-02-07 13:56:40 +01:00
Andrzej Krzemienski c81b9b098b fix constexpr reset 2026-02-07 13:36:08 +01:00
Andrzej Krzemienski 7b078be18d demove deprecation warnings 2026-02-07 13:23:04 +01:00
Andrzej Krzemienski 3df23370e6 make optional constexpr in C++14 2026-02-07 02:12:24 +01:00
Andrzej Krzemieński bfdf0c73f9 Merge pull request #139 from Flamefire/patch-1
Fix node 20 issue on GHA CI
2024-12-08 17:21:21 +01:00
Alexander Grund e1c6b5b737 Update containers 2024-12-08 14:43:18 +01:00
Alexander Grund 1a8c2dcafd Use hosted node 2024-12-08 13:11:03 +01:00
Alexander Grund 6134d0c274 Fix node 20 issue on GHA CI 2024-12-07 19:43:22 +01:00
Andrzej Krzemienski 121f3efde9 add note about range interface to the relnotes 2024-12-04 00:23:27 +01:00
34 changed files with 1600 additions and 574 deletions
+15 -14
View File
@@ -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
+1 -1
View File
@@ -2,7 +2,7 @@
[quickbook 1.4]
[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]
-1
View File
@@ -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]
+2
View File
@@ -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__
[caution The support for in-place factories is deprecated. Use constructor taking `in_place_init` tag and function `.emplace()` instead.]
[endsect]
+40 -42
View File
@@ -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,42 @@ 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__]``
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 +212,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 +237,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__]``
+55 -62
View File
@@ -23,7 +23,7 @@ __SPACE__
[#reference_optional_constructor]
[: `optional<T>::optional() noexcept;`]
[: `constexpr optional<T>::optional() noexcept;`]
* [*Effect:] Default-Constructs an `optional`.
* [*Postconditions:] `*this` is [_uninitialized].
@@ -38,7 +38,7 @@ __SPACE__
[#reference_optional_constructor_none_t]
[: `optional<T>::optional( none_t ) noexcept;`]
[: `constexpr optional<T>::optional( none_t ) noexcept;`]
* [*Effect:] Constructs an `optional` uninitialized.
* [*Postconditions:] `*this` is [_uninitialized].
@@ -56,7 +56,7 @@ __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 +78,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 +99,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 +114,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 +144,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 +178,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 +202,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 +226,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 +251,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)...`.
@@ -302,7 +302,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 +502,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;
@@ -540,15 +540,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 +563,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 +585,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 +596,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 +620,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 +630,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 +658,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 +685,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 +695,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 +714,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 +723,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 +744,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;`
@@ -793,8 +801,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 +820,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 +855,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.
+14 -1
View File
@@ -9,7 +9,20 @@
]
[section Dependencies and Portability]
[section Dependencies and Portability][#minimum_system_requirements]
[section Minimum System Requirements]
This library requires C++11 as minimum. However some features are disabled.
For C++14 and higher this library provides a `constexpr` interface for non-mutable
member functions and some mutable member functions.
[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 Dependencies]
The implementation uses the following other Boost modules:
+9 -1
View File
@@ -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,10 @@
[section:relnotes Release Notes]
[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.
@@ -19,6 +23,10 @@
* Dropped dependency on Boost.StaticAssert.
* Dropped dependency on Boost.Move.
* A bit faster implementation of some relational operations.
* *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`.
* 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].
@@ -0,0 +1,187 @@
// 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>
#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,639 @@
// 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_() {};
template <class... Args>
constexpr constexpr_union_storage_t( Args&&... args ) : value_(forward_<Args>(args)...) {}
//~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_() {};
template <class... Args>
constexpr fallback_union_storage_t( Args&&... args ) : value_(forward_<Args>(args)...) {}
~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;
};
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(); }
};
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;
}
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(cond ? storage_t(v) : storage_t())
{}
constexpr optional(bool cond, T&& v)
: storage(cond ? storage_t(optional_detail::move_(v)) : storage_t())
{}
constexpr optional(const optional& rhs)
: storage(rhs.is_initialized() ? storage_t(*rhs) : storage_t())
{}
constexpr optional(optional&& rhs)
noexcept(::std::is_nothrow_move_constructible<T>::value)
: storage(rhs.is_initialized() ? storage_t(*optional_detail::move_(rhs)) : storage_t())
{}
template <typename U, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U const&>)>
constexpr explicit optional(optional<U> const& rhs)
: storage(rhs.is_initialized() ? storage_t(in_place_init, *rhs) : storage_t())
{}
template <typename U, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U&&>)>
constexpr explicit optional(optional<U> && rhs)
: storage(rhs.is_initialized() ? storage_t(in_place_init, *optional_detail::move_(rhs)) : storage_t())
{}
template <typename... Args>
constexpr explicit optional( in_place_init_if_t, bool cond, Args&&... args )
: storage( cond ? storage_t(in_place_init, optional_detail::forward_<Args>(args)...) : storage_t() )
{}
#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()
{
factory.template apply<T>(this->dataptr());
storage.init_ = true;
}
template <typename U,
BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, 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 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_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();
factory.template apply<T>(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
+102 -227
View File
@@ -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,20 @@
#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 +147,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 +167,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 +188,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 +197,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 +238,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 +304,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 +318,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 +351,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 +361,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 +369,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 +377,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 +386,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 +431,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 +442,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 +467,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 +518,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 +566,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 +644,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 +653,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 +687,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 +706,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 +726,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 +745,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 +767,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 +803,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 +820,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 +840,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 +884,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 +909,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 +925,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 +934,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 +974,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 +1006,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 +1017,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
+14 -4
View File
@@ -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
+1 -1
View File
@@ -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
{
+2
View File
@@ -37,7 +37,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 ;
+32
View File
@@ -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>());
}
+99
View File
@@ -0,0 +1,99 @@
// 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; }
};
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, "");
#ifndef BOOST_NO_CXX14_CONSTEXPR
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_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;
}
+1
View File
@@ -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
@@ -29,4 +29,3 @@ void test_implicit_conversion_to_bool()
boost::optional<T> opt;
opt.value_or(U());
}
+23
View File
@@ -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);
}
+36 -36
View File
@@ -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);
+3
View File
@@ -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
+2 -1
View File
@@ -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
+4
View File
@@ -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();
}
+8 -3
View File
@@ -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()