Compare commits

...

22 Commits

Author SHA1 Message Date
Andrzej Krzemienski ecb241a919 tests: remove all -Wall warnings 2026-02-25 22:49:18 +01:00
Andrzej Krzemieński ff710d113c Merge pull request #145 from alandefreitas/fix/maybe-uninitialized-pragma
fix: add -Wmaybe-uninitialized pragma to union storage constructors
2026-02-25 17:42:43 +01:00
Alan de Freitas 88e2378c8a Add -Wmaybe-uninitialized pragma to union storage constructors
GCC 7+ produces false-positive -Wmaybe-uninitialized warnings at -O3
when deeply inlining through union constructors that initialize one
member while another (dummy_) exists. This is the same class of false
positive addressed in boostorg/variant2#55.

The pragmas are placed around the forwarding constructors in both
constexpr_union_storage_t and fallback_union_storage_t.
2026-02-24 12:11:51 -05:00
Andrzej Krzemienski fa52755c88 docs update 2026-02-20 16:14:53 +01:00
Andrzej Krzemienski 76be15bfeb update release notes 2026-02-18 21:10:45 +01:00
Andrzej Krzemienski 5d8e50a9aa add conversion from optional T to optional ref T 2026-02-18 16:52:52 +01:00
Andrzej Krzemienski 37513ddbbf remove traces of Boost.Assert 2026-02-18 13:23:48 +01:00
Andrzej Krzemienski 953b678b39 docs: minor fixes 2026-02-17 16:24:55 +01:00
Andrzej Krzemienski b2057c8dfe MSVC 14.1 fix -- 3rd attempt 2026-02-16 15:40:05 +01:00
Andrzej Krzemienski 1c13f5f724 MSVC 14.1 fix -- 2nd attempt 2026-02-16 13:20:03 +01:00
Andrzej Krzemienski aa1cf1e76c Work around the MSVC 14.1 bug 2026-02-16 01:13:53 +01:00
Andrzej Krzemienski 938502da88 fix bug with factories + conversions 2026-02-10 22:02:50 +01:00
Andrzej Krzemienski 046357ce54 Add more robust constexpr support 2026-02-10 19:30:11 +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
47 changed files with 2146 additions and 617 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
+2 -2
View File
@@ -1,8 +1,8 @@
[library Boost.Optional
[quickbook 1.4]
[quickbook 1.7]
[authors [Cacciola Carballal, Fernando Luis]]
[copyright 2003-2007 Fernando Luis Cacciola Carballal]
[copyright 2014-2024 Andrzej Krzemieński]
[copyright 2014-2026 Andrzej Krzemieński]
[category miscellaneous]
[id optional]
[dirname optional]
-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]
+12
View File
@@ -50,6 +50,18 @@ In the general case, the internal representation is something equivalent to:
alignas(T) char _value [sizeof(T)];
};
or:
template <typename T>
class Optional
{
bool _has_value = false;
union {
T _value;
DummyType _non_value;
};
};
Next, because we need to pass around these "optional" `int`s as normal `int`s,
like returning them from functions, when copying, we need to copy `_has_value`,
which indicates whether we have the value or not, and, if we do have value, and
+3 -1
View File
@@ -27,7 +27,7 @@ rather than the reference itself.
On compilers that do not conform to Standard C++ rules of reference binding,
some operations on optional references are disabled in order to prevent subtle
bugs. For more details see
[link boost_optional.dependencies_and_portability.optional_reference_binding Dependencies and Portability section].
[link optional_reference_binding Dependencies and Portability section].
]
[heading Rvalue references]
@@ -39,6 +39,8 @@ Rvalue references and lvalue references to const have the ability in C++ to exte
[endsect]
[#optional_ref_rebinding_semantics]
[section Rebinding semantics for assignment of optional references]
If you assign to an ['uninitialized ] `optional<T&>` the effect is to bind (for
+4 -2
View File
@@ -1,5 +1,5 @@
[section In-Place Factories]
[section:in_place_factories In-Place Factories][#boost_optional_factories]
One of the typical problems with wrappers and containers is that their
interfaces usually provide an operation to initialize or assign the
@@ -136,4 +136,6 @@ In-place factories can be used generically by the wrapper and user as follows:
The factories are implemented in the headers: __IN_PLACE_FACTORY_HPP__ and __TYPED_IN_PLACE_FACTORY_HPP__
[endsect]
[caution The support for in-place factories is deprecated. Use constructor taking `in_place_init` tag and function `.emplace()` instead.]
[endsect:in_place_factories]
+1 -1
View File
@@ -8,7 +8,7 @@ The very minimum requirement of `optional<T>` is that `T` is a complete type and
assert(!o); //
o.value(); // always throws
But this is practically useless. In order for `optional<T>` to be able to do anything useful and offer all the spectrum of ways of accessing the contained value, `T` needs to have at least one accessible constructor. In that case you need to initialize the optional object with function `emplace()`, or if your compiler does not support it, resort to [link boost_optional.design.in_place_factories In-Place Factories]:
But this is practically useless. In order for `optional<T>` to be able to do anything useful and offer all the spectrum of ways of accessing the contained value, `T` needs to have at least one accessible constructor. In that case you need to initialize the optional object with function `emplace()`, or if your compiler does not support it, resort to [link boost_optional_factories In-Place Factories]:
optional<T> o;
o.emplace("T", "ctor", "params");
+14 -3
View File
@@ -2,7 +2,7 @@
Boost.Optional
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
Copyright (c) 2015 Andrzej Krzemienski
Copyright (c) 2015 Andrzej Krzemieński
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
@@ -15,14 +15,25 @@
```
namespace boost {
class none_t {/* see below */};
class none_t
{
friend constexpr bool operator==(none_t, none_t) = default;
/* see below */
};
inline constexpr none_t none (/* see below */);
} // namespace boost
```
Class `none_t` is meant to serve as a tag for selecting appropriate overloads of from `optional`'s interface. It is an empty, trivially copyable class with disabled default constructor.
Class `none_t` is meant to serve as a tag for selecting appropriate overloads of from `optional`'s interface.
It is an empty class.
It is [@https://en.cppreference.com/w/cpp/named_req/TriviallyCopyable.html trivially copyable].
It is ['not] [@https://en.cppreference.com/w/cpp/named_req/DefaultConstructible default-constructible].
It models concept [@https://en.cppreference.com/w/cpp/concepts/equality_comparable `std::equality_comparable`].
Constant `none` is used to indicate an optional object that does not contain a value in initialization, assignment and relational operations of `optional`.
+43 -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,45 @@ They are empty, trivially copyable classes with disabled default constructor.
template<class TypedInPlaceFactory> optional& operator = ( TypedInPlaceFactory const& f ) ; ``[link reference_optional_operator_equal_factory __GO_TO__]``
T const& get() const ; ``[link reference_optional_get __GO_TO__]``
T& get() ; ``[link reference_optional_get __GO_TO__]``
constexpr T const& get() const ; ``[link reference_optional_get __GO_TO__]``
constexpr T& get() ; ``[link reference_optional_get __GO_TO__]``
T const* operator ->() const ; ``[link reference_optional_operator_arrow __GO_TO__]``
T* operator ->() ; ``[link reference_optional_operator_arrow __GO_TO__]``
constexpr T const* operator ->() const ; ``[link reference_optional_operator_arrow __GO_TO__]``
constexpr T* operator ->() ; ``[link reference_optional_operator_arrow __GO_TO__]``
T const& operator *() const& ; ``[link reference_optional_operator_asterisk __GO_TO__]``
T& operator *() & ; ``[link reference_optional_operator_asterisk __GO_TO__]``
T&& operator *() && ; ``[link reference_optional_operator_asterisk_move __GO_TO__]``
constexpr T const& operator *() const& ; ``[link reference_optional_operator_asterisk __GO_TO__]``
constexpr T& operator *() & ; ``[link reference_optional_operator_asterisk __GO_TO__]``
constexpr T&& operator *() && ; ``[link reference_optional_operator_asterisk_move __GO_TO__]``
T const& value() const& ; ``[link reference_optional_value __GO_TO__]``
T& value() & ; ``[link reference_optional_value __GO_TO__]``
T&& value() && ; ``[link reference_optional_value_move __GO_TO__]``
constexpr T const& value() const& ; ``[link reference_optional_value __GO_TO__]``
constexpr T& value() & ; ``[link reference_optional_value __GO_TO__]``
constexpr T&& value() && ; ``[link reference_optional_value_move __GO_TO__]``
template<class U> T value_or( U && v ) const& ; ``[link reference_optional_value_or __GO_TO__]``
template<class U> T value_or( U && v ) && ; ``[link reference_optional_value_or_move __GO_TO__]``
template<class U> constexpr T value_or( U && v ) const& ; ``[link reference_optional_value_or __GO_TO__]``
template<class U> constexpr T value_or( U && v ) && ; ``[link reference_optional_value_or_move __GO_TO__]``
template<class F> T value_or_eval( F f ) const& ; ``[link reference_optional_value_or_call __GO_TO__]``
template<class F> T value_or_eval( F f ) && ; ``[link reference_optional_value_or_call_move __GO_TO__]``
template<class F> constexpr T value_or_eval( F f ) const& ; ``[link reference_optional_value_or_call __GO_TO__]``
template<class F> constexpr T value_or_eval( F f ) && ; ``[link reference_optional_value_or_call_move __GO_TO__]``
template<class F> auto map( F f ) const& -> ``['see below]``; ``[link reference_optional_map __GO_TO__]``
template<class F> auto map( F f ) & -> ``['see below]``; ``[link reference_optional_map __GO_TO__]``
template<class F> auto map( F f ) && -> ``['see below]``; ``[link reference_optional_map_move __GO_TO__]``
template<class F> constexpr auto map( F f ) const& -> ``['see below]``; ``[link reference_optional_map __GO_TO__]``
template<class F> constexpr auto map( F f ) & -> ``['see below]``; ``[link reference_optional_map __GO_TO__]``
template<class F> constexpr auto map( F f ) && -> ``['see below]``; ``[link reference_optional_map_move __GO_TO__]``
template<class F> auto flat_map( F f ) const& -> ``['see below]``; ``[link reference_optional_flat_map __GO_TO__]``
template<class F> auto flat_map( F f ) & -> ``['see below]``; ``[link reference_optional_flat_map __GO_TO__]``
template<class F> auto flat_map( F f ) && -> ``['see below]``; ``[link reference_optional_flat_map_move __GO_TO__]``
template<class F> constexpr auto flat_map( F f ) const& -> ``['see below]``; ``[link reference_optional_flat_map __GO_TO__]``
template<class F> constexpr auto flat_map( F f ) & -> ``['see below]``; ``[link reference_optional_flat_map __GO_TO__]``
template<class F> constexpr auto flat_map( F f ) && -> ``['see below]``; ``[link reference_optional_flat_map_move __GO_TO__]``
constexpr operator optional<T&>() & noexcept; ``[link reference_optional_conversion_to_ref __GO_TO__]``
constexpr operator optional<T const&>() const& noexcept; ``[link reference_optional_conversion_to_ref __GO_TO__]``
T const* get_ptr() const ; ``[link reference_optional_get_ptr __GO_TO__]``
T* get_ptr() ; ``[link reference_optional_get_ptr __GO_TO__]``
bool has_value() const noexcept ; ``[link reference_optional_operator_bool __GO_TO__]``
constexpr bool has_value() const noexcept ; ``[link reference_optional_operator_bool __GO_TO__]``
explicit operator bool() const noexcept ; ``[link reference_optional_operator_bool __GO_TO__]``
constexpr explicit operator bool() const noexcept ; ``[link reference_optional_operator_bool __GO_TO__]``
bool operator!() const noexcept ; ``[link reference_optional_operator_not __GO_TO__]``
void reset() noexcept ; ``[link reference_optional_reset __GO_TO__]``
constexpr void reset() noexcept ; ``[link reference_optional_reset __GO_TO__]``
// deprecated methods
@@ -214,7 +215,7 @@ They are empty, trivially copyable classes with disabled default constructor.
void reset ( T const& ) ; ``[link reference_optional_reset_value __GO_TO__]``
// (deprecated)
bool is_initialized() const ; ``[link reference_optional_is_initialized __GO_TO__]``
constexpr bool is_initialized() const ; ``[link reference_optional_is_initialized __GO_TO__]``
// (deprecated)
T const& get_value_or( T const& default ) const ; ``[link reference_optional_get_value_or_value __GO_TO__]``
@@ -239,9 +240,9 @@ They are empty, trivially copyable classes with disabled default constructor.
typedef T* pointer_type;
typedef T* pointer_const_type; // no const propagation
optional () noexcept ; ``[link reference_optional_ref_default_ctor __GO_TO__]``
constexpr optional () noexcept ; ``[link reference_optional_ref_default_ctor __GO_TO__]``
optional ( none_t ) noexcept ; ``[link reference_optional_ref_default_ctor __GO_TO__]``
constexpr optional ( none_t ) noexcept ; ``[link reference_optional_ref_default_ctor __GO_TO__]``
template<class R> optional(R&& r) noexcept ; ``[link reference_optional_ref_value_ctor __GO_TO__]``
+88 -74
View File
@@ -2,6 +2,7 @@
Boost.Optional
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
Copyright (C) 2014 - 2026 Andrzej Krzemieński.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
@@ -23,40 +24,40 @@ __SPACE__
[#reference_optional_constructor]
[: `optional<T>::optional() noexcept;`]
[: `constexpr optional<T>::optional() noexcept;`]
* [*Effect:] Default-Constructs an `optional`.
* [*Postconditions:] `*this` is [_uninitialized].
* [*Notes:] T's default constructor [_is not] called.
* [*Postconditions:] `*this` does ['not] contain a value (is "uninitialized").
* [*Remarks:] No contained value is initialized. For every object type `T` these constructors are core constant expressions.
* [*Example:]
``
optional<T> def ;
assert ( !def ) ;
optional<T> oN ;
assert ( !oN ) ;
``
__SPACE__
[#reference_optional_constructor_none_t]
[: `constexpr optional<T>::optional( none_t ) noexcept;`]
[: `optional<T>::optional( none_t ) noexcept;`]
* [*Effect:] Constructs an `optional` uninitialized.
* [*Postconditions:] `*this` is [_uninitialized].
* [*Notes:] `T`'s default constructor [_is not] called. The expression
* [*Postconditions:] `*this` does ['not] contain a value (is "uninitialized").
* [*Remarks:] No contained value is initialized. For every object type `T` these constructors are core constant expressions. The expression
`boost::none` denotes an instance of `boost::none_t` that can be used as
the parameter.
* [*Example:]
``
#include <boost/none.hpp>
optional<T> n(none) ;
assert ( !n ) ;
assert ( n == none ) ;
``
__SPACE__
[#reference_optional_constructor_value]
[: `optional<T>::optional( T const& v )`]
[: `constexpr optional<T>::optional( T const& v )`]
* [*Requires:] `is_copy_constructible<T>::value` is `true`.
* [*Effect:] Directly-Constructs an `optional`.
@@ -78,7 +79,7 @@ __SPACE__
[#reference_optional_constructor_move_value]
[: `optional<T>::optional( T&& v )`]
[: `constexpr optional<T>::optional( T&& v )`]
* [*Requires:] `is_move_constructible<T>::value` is `true`.
* [*Effect:] Directly-Move-Constructs an `optional`.
@@ -99,7 +100,7 @@ __SPACE__
[#reference_optional_constructor_bool_value]
[: `optional<T>::optional( bool condition, T const& v ) ;` ]
[: `constexpr optional<T>::optional( bool condition, T const& v ) ;` ]
* If condition is true, same as:
@@ -114,7 +115,7 @@ __SPACE__
[#reference_optional_constructor_optional]
[: `optional<T>::optional( optional const& rhs );`]
[: `constexpr optional<T>::optional( optional const& rhs );`]
* [*Requires:] `is_copy_constructible<T>::value` is `true`.
* [*Effect:] Copy-Constructs an `optional`.
@@ -144,7 +145,7 @@ __SPACE__
[#reference_optional_move_constructor_optional]
[: `optional<T>::optional( optional&& rhs ) noexcept(`['see below]`);`]
[: `constexpr optional<T>::optional( optional&& rhs ) noexcept(`['see below]`);`]
* [*Requires:] `is_move_constructible<T>::value` is `true`.
* [*Effect:] Move-constructs an `optional`.
@@ -178,7 +179,7 @@ __SPACE__
[#reference_optional_constructor_other_optional]
[: `template<U> explicit optional<T>::optional( optional<U> const& rhs );`]
[: `template<U> constexpr explicit optional<T>::optional( optional<U> const& rhs );`]
* [*Effect:] Copy-Constructs an `optional`.
* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and its
@@ -202,7 +203,7 @@ __SPACE__
[#reference_optional_move_constructor_other_optional]
[: `template<U> explicit optional<T>::optional( optional<U>&& rhs );`]
[: `template<U> constexpr explicit optional<T>::optional( optional<U>&& rhs );`]
* [*Effect:] Move-constructs an `optional`.
* [*Postconditions:] If `rhs` is initialized, `*this` is initialized and its
@@ -226,7 +227,7 @@ __SPACE__
[#reference_optional_in_place_init]
[: `template<class... Args> explicit optional<T>::optional( in_place_init_t, Args&&... ars );`]
[: `template<class... Args> constexpr explicit optional<T>::optional( in_place_init_t, Args&&... ars );`]
* [*Requires:] `is_constructible_v<T, Args&&...>` is `true`.
* [*Effect:] Initializes the contained value as if direct-non-list-initializing an object of type `T` with the
@@ -251,7 +252,7 @@ __SPACE__
[#reference_optional_in_place_init_if]
[: `template<class... Args> explicit optional<T>::optional( in_place_init_if_t, bool condition, Args&&... ars );`]
[: `template<class... Args> constexpr explicit optional<T>::optional( in_place_init_if_t, bool condition, Args&&... ars );`]
* [*Requires:] `is_constructible_v<T, Args&&...>` is `true`.
* [*Effect:] If `condition` is `true`, initializes the contained value as if direct-non-list-initializing an object of type `T` with the arguments `std::forward<Args>(args)...`.
@@ -281,7 +282,7 @@ factory.
* [*Postconditions: ] `*this` is [_initialized] and its value is ['directly given]
from the factory `f` (i.e., the value [_is not copied]).
* [*Throws:] Whatever the `T` constructor called by the factory throws.
* [*Notes:] See [link boost_optional.design.in_place_factories In-Place Factories]
* [*Notes:] See [link boost_optional_factories In-Place Factories]
* [*Exception Safety:] Exceptions can only be thrown during the call to
the `T` constructor used by the factory; in that case, this constructor has
no effect.
@@ -302,7 +303,7 @@ __SPACE__
[#reference_optional_operator_equal_none_t]
[: `optional& optional<T>::operator= ( none_t ) noexcept;`]
[: `constexpr optional& optional<T>::operator= ( none_t ) noexcept;`]
* [*Effect:] If `*this` is initialized destroys its contained value.
* [*Postconditions: ] `*this` is uninitialized.
@@ -502,7 +503,7 @@ __SPACE__
* [*Postconditions: ] `*this` is [_initialized].
* [*Throws:] Whatever the selected `T`'s constructor throws.
* [*Exception Safety:] If an exception is thrown during the initialization of `T`, `*this` is ['uninitialized].
* [*Notes:] `T` need not be __MOVE_CONSTRUCTIBLE__ or `MoveAssignable`.
* [*Notes:] `T` need not be __MOVE_CONSTRUCTIBLE__ or `MoveAssignable`.
* [*Example:]
``
T v;
@@ -524,7 +525,7 @@ factory.
* [*Postconditions: ] `*this` is [_initialized] and its value is ['directly given]
from the factory `f` (i.e., the value [_is not copied]).
* [*Throws:] Whatever the `T` constructor called by the factory throws.
* [*Notes:] See [link boost_optional.design.in_place_factories In-Place Factories]
* [*Notes:] See [link boost_optional_factories In-Place Factories]
* [*Exception Safety:] Exceptions can only be thrown during the call to
the `T` constructor used by the factory; in that case, the `optional` object
will be reset to be ['uninitialized].
@@ -540,15 +541,15 @@ __SPACE__
[#reference_optional_reset]
[: `void optional<T>::reset() noexcept ;`]
[: `constexpr void optional<T>::reset() noexcept ;`]
* [*Effects:] Same as `operator=( none_t );`
__SPACE__
[#reference_optional_get]
[: `T const& optional<T>::get() const ;`]
[: `T& optional<T>::get() ;`]
[: `constexpr T const& optional<T>::get() const ;`]
[: `constexpr T& optional<T>::get() ;`]
[: `inline T const& get ( optional<T> const& ) ;`]
[: `inline T& get ( optional<T> &) ;`]
@@ -563,8 +564,8 @@ __SPACE__
[#reference_optional_operator_asterisk]
[: `T const& optional<T>::operator*() const& ;`]
[: `T& optional<T>::operator*() &;`]
[: `constexpr T const& optional<T>::operator*() const& ;`]
[: `constexpr T& optional<T>::operator*() &;`]
* [*Requires:] `*this` is initialized
* [*Returns:] A reference to the contained value
@@ -585,7 +586,7 @@ __SPACE__
[#reference_optional_operator_asterisk_move]
[: `T&& optional<T>::operator*() &&;`]
[: `constexpr T&& optional<T>::operator*() &&;`]
* [*Requires:] `*this` contains a value.
* [*Effects:] Equivalent to `return std::move(*val);`.
@@ -596,8 +597,8 @@ __SPACE__
[#reference_optional_value]
[: `T const& optional<T>::value() const& ;`]
[: `T& optional<T>::value() & ;`]
[: `constexpr T const& optional<T>::value() const& ;`]
[: `constexpr T& optional<T>::value() & ;`]
* [*Effects:] Equivalent to `return bool(*this) ? *val : throw bad_optional_access();`.
* [*Notes:] On compilers that do not support ref-qualifiers on member functions these two overloads are replaced with the classical two: a `const` and non-`const` member functions.
@@ -620,7 +621,7 @@ __SPACE__
[#reference_optional_value_move]
[: `T&& optional<T>::value() && ;`]
[: `constexpr T&& optional<T>::value() && ;`]
* [*Effects:] Equivalent to `return bool(*this) ? std::move(*val) : throw bad_optional_access();`.
* [*Notes:] On compilers that do not support ref-qualifiers on member functions this overload is not present.
@@ -630,17 +631,25 @@ __SPACE__
[#reference_optional_value_or]
[: `template<class U> T optional<T>::value_or(U && v) const& ;`]
[: `template<class U = T> constexpr T optional<T>::value_or(U && v) const& ;`]
* [*Effects:] Equivalent to `if (*this) return **this; else return std::forward<U>(v);`.
* [*Remarks:] If `T` is not __COPY_CONSTRUCTIBLE__ or `U &&` is not convertible to `T`, the program is ill-formed.
* [*Notes:] On compilers that do not support ref-qualifiers on member functions this overload is replaced with the `const`-qualified member function. On compilers without rvalue reference support the type of `v` becomes `U const&`.
* [*Example:]
``
optional<int> oN, o1(1);
assert (o1.value_or(9) == 1);
assert (oN.value_or(9) == 9);
assert (oN.value_or({}) == 0);
``
__SPACE__
[#reference_optional_value_or_move]
[: `template<class U> T optional<T>::value_or(U && v) && ;`]
[: `template<class U> constexpr T optional<T>::value_or(U && v) && ;`]
* [*Effects:] Equivalent to `if (*this) return std::move(**this); else return std::forward<U>(v);`.
* [*Remarks:] If `T` is not __MOVE_CONSTRUCTIBLE__ or `U &&` is not convertible to `T`, the program is ill-formed.
@@ -650,7 +659,7 @@ __SPACE__
[#reference_optional_value_or_call]
[: `template<class F> T optional<T>::value_or_eval(F f) const& ;`]
[: `template<class F> constexpr T optional<T>::value_or_eval(F f) const& ;`]
* [*Requires:] `T` is __COPY_CONSTRUCTIBLE__ and `F` models a __SGI_GENERATOR__ whose result type is convertible to `T`.
* [*Effects:] `if (*this) return **this; else return f();`.
@@ -677,7 +686,7 @@ __SPACE__
[#reference_optional_value_or_call_move]
[: `template<class F> T optional<T>::value_or_eval(F f) && ;`]
[: `template<class F> constexpr T optional<T>::value_or_eval(F f) && ;`]
* [*Requires:] `T` is __MOVE_CONSTRUCTIBLE__ and `F` models a __SGI_GENERATOR__ whose result type is convertible to `T`.
* [*Effects:] `if (*this) return std::move(**this); else return f();`.
@@ -687,8 +696,8 @@ __SPACE__
[#reference_optional_map]
[: `template<class F> auto optional<T>::map(F f) const& -> `['see below]` ;`]
[: `template<class F> auto optional<T>::map(F f) & -> `['see below]` ;`]
[: `template<class F> constexpr auto optional<T>::map(F f) const& -> `['see below]` ;`]
[: `template<class F> constexpr auto optional<T>::map(F f) & -> `['see below]` ;`]
* [*Effects:] `if (*this) return f(**this); else return none;`
* [*Notes:] The return type of these overloads is `optional<decltype(f(**this))>`. On compilers that do not support ref-qualifiers on member functions, these two (as well as the next one) overloads are replaced with good old const and non-const overloads.
@@ -706,7 +715,7 @@ __SPACE__
[#reference_optional_map_move]
[: `template<class F> auto optional<T>::map(F f) && -> `['see below]` ;`]
[: `template<class F> constexpr auto optional<T>::map(F f) && -> `['see below]` ;`]
* [*Effects:] `if (*this) return f(std::move(**this)); else return none;`
* [*Notes:] The return type of this overload is `optional<decltype(f(istd::move(**this)))>`.
@@ -715,8 +724,8 @@ __SPACE__
[#reference_optional_flat_map]
[: `template<class F> auto optional<T>::flat_map(F f) const& -> `['see below]` ;`]
[: `template<class F> auto optional<T>::flat_map(F f) & -> `['see below]` ;`]
[: `template<class F> constexpr auto optional<T>::flat_map(F f) const& -> `['see below]` ;`]
[: `template<class F> constexpr auto optional<T>::flat_map(F f) & -> `['see below]` ;`]
* [*Requires:] The return type of expression `f(**this)` is `optional<U>` for some object or reference type `U`.
* [*Effects:] `if (*this) return f(**this); else return none;`
@@ -736,7 +745,7 @@ __SPACE__
[#reference_optional_flat_map_move]
[: `template<class F> auto optional<T>::flat_map(F f) && -> `['see below]` ;`]
[: `template<class F> constexpr auto optional<T>::flat_map(F f) && -> `['see below]` ;`]
* [*Requires:] The return type of expression `f(std::move(**this))` is `optional<U>` for some object or reference type `U`.
* [*Effects:] `if (*this) return f(std::move(**this)); else return none;`
@@ -744,6 +753,26 @@ __SPACE__
__SPACE__
[#reference_optional_conversion_to_ref]
[: `constexpr optional<T>::operator optional<T&>() & noexcept ;`]
* [*Returns:] If `*this` contains a value `optional<T&>(**this)`, otherwise `optional<T&>()`.
[: `constexpr optional<T>::operator optional<T const&>() const& noexcept ;`]
* [*Returns:] If `*this` contains a value `optional<T const&>(**this)`, otherwise `optional<T&>()`.
* [*Example:]
``
const optional<int> oi = 1;
optional<const int&> ri = oi;
``
__SPACE__
[#reference_optional_get_value_or_value]
[: `T const& optional<T>::get_value_or( T const& default) const ;`]
@@ -793,8 +822,8 @@ __SPACE__
[#reference_optional_operator_arrow]
[: `T const* optional<T>::operator ->() const ;`]
[: `T* optional<T>::operator ->() ;`]
[: `constexpr T const* optional<T>::operator ->() const ;`]
[: `constexpr T* optional<T>::operator ->() ;`]
* [*Requires: ] `*this` is initialized.
* [*Returns:] A pointer to the contained value.
@@ -812,44 +841,29 @@ __SPACE__
[#reference_optional_operator_bool]
[: `explicit optional<T>::operator bool() const noexcept ;`]
[: `bool optional<T>::has_value() const noexcept ;`]
[: `constexpr explicit optional<T>::operator bool() const noexcept ;`]
[: `constexpr bool optional<T>::has_value() const noexcept ;`]
* [*Returns:] `get_ptr() != 0`.
* [*Notes:] On compilers that do not support explicit conversion operators this falls back to safe-bool idiom.
* [*Example:]
``
optional<T> def ;
assert ( def == 0 );
optional<T> opt ( v ) ;
assert ( opt );
assert ( opt != 0 );
optional<int> oN;
assert (!oN);
assert (!oN.has_value());
optional<int> o1(1);
assert (o1);
assert (o1.has_value());
assert (!!o1); // the "double-bang" idiom
``
__SPACE__
[#reference_optional_operator_not]
[: `bool optional<T>::operator!() noexcept ;`]
* [*Returns:] If `*this` is uninitialized, `true`; else `false`.
* [*Notes:] This operator is provided for those compilers which can't
use the ['unspecified-bool-type operator] in certain boolean contexts.
* [*Example:]
``
optional<T> opt ;
assert ( !opt );
*opt = some_T ;
// Notice the "double-bang" idiom here.
assert ( !!opt ) ;
``
__SPACE__
[#reference_optional_is_initialized]
[: `bool optional<T>::is_initialized() const ;`]
[: `constexpr bool optional<T>::is_initialized() const ;`]
* [*Deprecated:] Same as `explicit operator bool () ;`
@@ -862,8 +876,8 @@ __SPACE__
[#reference_optional_ref_default_ctor]
[: `optional<T&>::optional() noexcept;`]
[: `optional<T&>::optional(none_t) noexcept;`]
[: `constexpr optional<T&>::optional() noexcept;`]
[: `constexpr optional<T&>::optional(none_t) noexcept;`]
* [*Postconditions:] `bool(*this) == false`; `*this` refers to nothing.
@@ -963,7 +977,7 @@ __SPACE__
* [*Postconditions:] `bool(*this) == bool(rhs)`.
* [*Notes:] This behaviour is called ['rebinding semantics]. See [link boost_optional.design.optional_references.rebinding_semantics_for_assignment_of_optional_references here] for details.
* [*Notes:] This behaviour is called ['rebinding semantics]. See [link optional_ref_rebinding_semantics here] for details.
* [*Example:]
``
+1 -1
View File
@@ -11,7 +11,7 @@
[section Header <boost/optional.hpp>]
This is an alias for header [link boost_optional.reference.header__boost_optional_optional_hpp_.header_optional_optional `<boost/optional/optional.hpp>`].
This is an alias for header [link ref_header_optional_optional_hpp `<boost/optional/optional.hpp>`].
[endsect]
+56 -2
View File
@@ -9,7 +9,62 @@
]
[section Dependencies and Portability]
[section Dependencies and Portability][#minimum_system_requirements]
[section Minimum System Requirements]
This library requires C++11 as minimum. However, in C++11 some features are disabled.
[section:constexpr Support for `constexpr`]
[section C++11]
For compilers fully supporting C++11 (including unconstrained unions and ref-qualifiers),
for trivially-destructible `T`s, `optional<T>` is a ['literal type] and its constructors
with `this->has_value() == false` as postcondition:
* `optional()`,
* `optional(none_t)`,
are ['core constant expressions]. Even for other `T`s, these constructors are guaranteed to
perform ['constant initialization]: they are never subject to "initialization order fiasco".
Other constructors with `this->has_value() == true`
as postcondition are core constant expressions if the expression required to initialize
the contained value is a core constant expression. This includes constructors:
* `template <typename... Args> optional(in_place_init, Args&&...)`,
* `template <typename U> optional(U&&)`,
* `optional(const T&)`,
* `optional(T&&)`.
Other constructors, including the copy and move constructos, are ['not] core constant expressions.
Member functions `.has_value`, `operator bool` and (non)equality comparisons with `none` are core-constant expressions for trivially-destructible `T`s.
Also all `const`-qualified non-static member functions and comparison operators are core constant expressions, if the corresponding operations on `T`
are core constant expressions.
[endsect]
[section C++14]
For C++14 and higher this library, for trivially-destructible `T`s provides the `constexpr` interface for all mutable and non-mutable
member functions, as long as:
* the corresponding operations on `T` are core constant expressions and
* the member never attempts to change the `optional`'s state from not containing a value to containing a value.
[note For types that overload unary `operator&` (address) some member functions in `optional`, like `operator->`,
cannot be implemented as `constexpr` on some compilers.]
[endsect]
[section C++17]
In C++17 all non-deprecated constructors are core constant expressions as long as
`T` is a literal type and its constructor used is a core constant expression.
[endsect]
[endsect:constexpr]
[endsect]
[section Dependencies]
The implementation uses the following other Boost modules:
@@ -17,7 +72,6 @@ The implementation uses the following other Boost modules:
# assert
# config
# core
# static_assert
# throw_exception
# type_traits
+18 -3
View File
@@ -11,8 +11,7 @@
[section:std_comp Comparison with `std::optional`]
[table
[]
[table Comparison with `std::optional`
[ [[*`boost::optional`]] [[*`std::optional`]] [] ]
[ [`optional<int> o = none;`] [`optional<int> o = nullopt;`] [Different name for no-value tag.] ]
[ [`optional<X> o {in_place_init, a, b};`] [`optional<int> o {in_place, a, b};`] [Different name for in-place initialization tag.] ]
@@ -42,7 +41,23 @@
[ [`make_optional(cond, v);`] [] [No `make_optional` with condition in `std`.] ]
[ [] [`make_optional<T>(a, b);`] [No `make_optional` with specified `T` in `boost`.] ]
[ [`std::cout << optional<int>{};`] [] [No printing to IOStreams in `std`.]]
[ [`std::vector<optional<int>> rng;`
`std::ranges::find(rng, boost::none)`] [`std::vector<optional<int>> rng;`
`std::ranges::find(rng, boost::optional<int>{})`] [optional<T> is never [@https://en.cppreference.com/w/cpp/concepts/equality_comparable `std::equality_comparable_with`] `nullopt_t` in `std`. ] ]
[ [```
void test(vector<optional<T>> rng, T val) {
std::ranges::find(rng, val);
}
```] [```
void test(vector<optional<T>> rng, T val) {
std::ranges::find(rng, make_optional(val));
}
```] [For `std::optional`, code without `make_optional()` compiles but is ['undefined behavior] when `T` is itself an `optional`. ] ]
]
[endsect][/ std_comp]
+53 -2
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,57 @@
[section:relnotes Release Notes]
[heading Boost Release 1.91]
* For compilers with full C++11 support (including "unrestricted unions" and ref-qualifiers)
changed the implementation from aligned storage to union storage. This enables the gradual
`constexpr` support:
* In C++11, some constructors and `const`-qualified accessors become usable
in compile-time contexts (are ['core constant expressions]) for types
satisfying certain constraints.
* In C++14 even some mutating operations become core constant expressions (those
that do not require changing the state of `optional` from not having a value to
having a value), for co-operating types.
* In C++17 all constructors (including copy and move) become core constant expressions
for co-operating types.
This addresses issues [@https://github.com/boostorg/optional/issues/132 #132] and [@https://github.com/boostorg/optional/issues/143 #143].
* *Breaking change.* In the said implementation, abandoned the mechanism for customizing
`swap`. Hardly anyone knows about this mechanism and it was never documented.
* In the said implementation, applied a couple of small changes to get closer to the interface of `std::optional`:
* Enabled syntax `o = {}` for putting optional objects to no-value state.
* Enabled syntax `o.value_or({})`, which uses a default-constructed `T`.
* Construct `o = u`, where `o` is of type `optional<T>` and `u` is of type `U` convertible to `T`,
does not create a temporary `T`.
* In the said implementation, added a conversion from `optional<T>&` to `optional<T&>`. This addresses [@https://github.com/boostorg/optional/issues/142 issue #142].
* `none_t` is now `std::equality_comparable`, which means that `none_t` and `optional<T>`
model concept `std::equality_comparable_with` (for `std::equality_comparable` `T`s),
which means that you can `std::ranges::find(rng, boost::none)` for a range of optional objects.
* *Warning.* In the future releases we intend to introduce the range interface
in `optional`, so that `std::ranges::range<optional<T>>` will be `true`.
This may affect the overload resolution in programs that make decisions based
on predicates such as `std::ranges::range`. For instance, the following code
will start behaving differently:
```
template <typename T>
void serialize(T const& v)
{
if constexpr (std::ranges::range<T>)
serialize_as_range(v);
else if constexpr (custom::is_optional_like<T>)
serialize_as_optional(v);
else
serialize_as_value(v);
}
```
[heading Boost Release 1.87]
* *Breaking change.* Dropped support for C++03. C++11 is now the required minimum; at least some C++11 features.
@@ -22,7 +73,7 @@
* *Warning.* In the future releases we intend to introduce the range interface
into `optional`, so that `std::ranges::range<optional<T>>` will be `true`.
This may affect the overload resolution in programs that make decisions based
on predicates such as `std::ranges::range`.
on predicates such as `std::ranges::range`.
* Tags `in_place_init` and `in_place_init_if` become `inline constexpr` and therewith leave smaller footprint in the executable. This addresses [@https://github.com/boostorg/optional/issues/103 issue #103].
+6 -1
View File
@@ -25,7 +25,7 @@
#elif defined(BOOST_NO_CXX11_REF_QUALIFIERS) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DEFAULTED_MOVES)
BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Optional 1.83 and will be removed in Boost.Optional 1.88.")
BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Optional 1.83 and will be removed in Boost.Optional 1.92.")
#endif
@@ -46,6 +46,11 @@ struct none_t
{
struct init_tag{};
explicit BOOST_CONSTEXPR none_t(init_tag){} // to disable default constructor
#ifndef BOOST_OPTIONAL_DISABLE_EQUALITY_FOR_NONE
friend BOOST_CONSTEXPR bool operator==(none_t, none_t) { return true; }
friend BOOST_CONSTEXPR bool operator!=(none_t, none_t) { return false; }
#endif
};
#endif // old implementation workarounds
@@ -0,0 +1,188 @@
// Copyright (C) 2024 Ryan Malcolm Underwood.
// Copyright (C) 2026 Andrzej Krzemieński.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the authors at:
// akrzemi1@gmail.com
// typenametea@gmail.com
//
//
// This header provides definitions required by any specialization of
// optional<>.
#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_COMMON_DEFS_01FEB2026_HPP
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_COMMON_DEFS_01FEB2026_HPP
#include <boost/config.hpp>
#include <boost/core/addressof.hpp>
#include <type_traits>
#include <boost/optional/detail/optional_factory_support.hpp>
#ifndef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
#include <boost/type_traits/decay.hpp>
#include <boost/type_traits/is_base_of.hpp>
#endif
// This is needed for C++11, where constexpr functions must contain a single expression.
// We want to assert and then return.
#if defined NDEBUG
# define BOOST_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
#else
# define BOOST_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{BOOST_ASSERT(!(#CHECK));}(), (EXPR)))
#endif
#ifdef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
# define BOOST_OPTIONAL_DECAY(T) typename ::std::decay<T>::type
# define BOOST_OPTIONAL_IS_TAGGED(TAG, U) ::std::is_base_of<TAG, BOOST_OPTIONAL_DECAY(U)>
#else
# define BOOST_OPTIONAL_DECAY(T) BOOST_DEDUCED_TYPENAME boost::decay<T>::type
# define BOOST_OPTIONAL_IS_TAGGED(TAG, U) boost::is_base_of<TAG, BOOST_OPTIONAL_DECAY(U)>
#endif
namespace boost {
template <typename T> class optional;
// Boost-wide tags for recognizing "factories": a C++03 workaround
// for perfect forwarding.
class in_place_factory_base;
class typed_in_place_factory_base;
} // namespace boost
// Traits for recognizing in-place factories
namespace boost { namespace optional_detail {
template <typename U>
struct is_in_place_factory : BOOST_OPTIONAL_IS_TAGGED(boost::in_place_factory_base, U) {};
template <typename U>
struct is_typed_in_place_factory : BOOST_OPTIONAL_IS_TAGGED(boost::typed_in_place_factory_base, U) {};
}}
/** This is a set of declarations that repeat those from the Standard Library
header <utility> but without having to drag its entire content. They also
add missing capabilities, like constexpr, in older compiler versions.
*/
namespace boost { namespace optional_detail {
template <typename T>
T declval_();
template <class T>
inline constexpr T&& forward_(typename ::std::remove_reference<T>::type& t) noexcept
{
return static_cast<T&&>(t);
}
template <class T>
inline constexpr T&& forward_(typename ::std::remove_reference<T>::type&& t) noexcept
{
static_assert(!::std::is_lvalue_reference<T>::value, "Can not forward an rvalue as an lvalue.");
return static_cast<T&&>(t);
}
template <class T>
inline constexpr typename ::std::remove_reference<T>::type&& move_(T&& t) noexcept
{
return static_cast<typename ::std::remove_reference<T>::type&&>(t);
}
}} // namespace boost::optional_detail
/** This is a set of declarations that are not part of this library's interface.
They are implementation details.
*/
namespace boost { namespace optional_detail {
/** This struct is used for tagging types that want to be recognized as
`optional`. If your class inherits directly or indirectly from `optional_tag`
the type traits and overloads will treat it as `optional<>`.
*/
struct optional_tag {};
/** `optional_value_type`: given type `X`:
* if `X` is an instance of `boost::optional`, returns its value_type,
* otherwise we get a SFINAE-able error.
*/
template <typename X>
struct optional_value_type
{
};
template <typename U>
struct optional_value_type< ::boost::optional<U> >
{
typedef U type;
};
/** This is an approximation of a 1-argument C++17 std::invoke_result.
*/
template <typename F, typename Ref, typename Rslt = decltype(declval_<F>()(declval_<Ref>()))>
struct result_of
{
typedef Rslt type;
};
/** This type trait returns the following given the expression `f(ref)`:
* if the result is a specialization of `boost::optional`: its value_type,
* otherwise a SFINAE-able error.
*/
template <typename F, typename Ref, typename Rslt = typename optional_value_type<typename result_of<F, Ref>::type>::type>
struct result_value_type
{
typedef Rslt type;
};
}} // namespace boost::optional_detail
/** The following two tags are intended to be used by library users.
The additional namespace is used in order to prevent the ADL from
dragging all functions from namespace `boost` in any unqualified name lookup
when these tags are involved.
*/
namespace boost {
namespace optional_ns {
/// a tag for in-place initialization of contained value
struct in_place_init_t
{
struct init_tag{};
BOOST_CONSTEXPR explicit in_place_init_t(init_tag){}
};
BOOST_INLINE_CONSTEXPR in_place_init_t in_place_init ((in_place_init_t::init_tag()));
/// a tag for conditional in-place initialization of contained value
struct in_place_init_if_t
{
struct init_tag{};
BOOST_CONSTEXPR explicit in_place_init_if_t(init_tag){}
};
BOOST_INLINE_CONSTEXPR in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag()));
} // namespace optional_ns
using optional_ns::in_place_init_t;
using optional_ns::in_place_init;
using optional_ns::in_place_init_if_t;
using optional_ns::in_place_init_if;
} // namespace boost
#endif // BOOST_OPTIONAL_DETAIL_OPTIONAL_COMMON_DEFS_01FEB2026_HPP
@@ -27,10 +27,4 @@ namespace boost_optional_detail
}
}
namespace boost
{
class in_place_factory_base ;
class typed_in_place_factory_base ;
}
#endif // header guard
@@ -12,7 +12,7 @@
#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_HASH_AJK_20MAY2022_HPP
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_HASH_AJK_20MAY2022_HPP
#include <boost/optional/optional_fwd.hpp>
//#include <boost/optional/optional_fwd.hpp>
#include <boost/config.hpp>
#if !defined(BOOST_OPTIONAL_CONFIG_DO_NOT_SPECIALIZE_STD_HASH) && !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
@@ -0,0 +1,117 @@
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
// Copyright (C) 2014 - 2026 Andrzej Krzemieński.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the authors at:
// fernando_cacciola@hotmail.com
// akrzemi1@gmail.com
//
// You can file a GitHub issue at:
// https://github.com/boostorg/optional/issues
// This header provides definitions rof nonmember functions that still constitute
// the interface for class optional<>.
#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_NONMEMBER_INTERFACE_01FEB2026_HPP
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_NONMEMBER_INTERFACE_01FEB2026_HPP
namespace boost {
template <class T>
inline BOOST_CXX14_CONSTEXPR
optional<BOOST_OPTIONAL_DECAY(T)> make_optional ( T && v )
{
return optional<BOOST_OPTIONAL_DECAY(T)>(optional_detail::forward_<T>(v));
}
// Returns optional<T>(cond,v)
template <class T>
inline BOOST_CXX14_CONSTEXPR
optional<BOOST_OPTIONAL_DECAY(T)> make_optional ( bool cond, T && v )
{
return optional<BOOST_OPTIONAL_DECAY(T)>(cond,optional_detail::forward_<T>(v));
}
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
// No-throw
template <class T>
inline BOOST_CXX14_CONSTEXPR
BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
get ( optional<T> const& opt )
{
return opt.get() ;
}
template <class T>
inline BOOST_CXX14_CONSTEXPR
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
get ( optional<T>& opt )
{
return opt.get() ;
}
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
// No-throw
template<class T>
inline BOOST_CXX14_CONSTEXPR
BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
get ( optional<T> const* opt )
{
return opt->get_ptr() ;
}
template<class T>
inline BOOST_CXX14_CONSTEXPR
BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
get ( optional<T>* opt )
{
return opt->get_ptr() ;
}
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
// No-throw
template<class T>
inline BOOST_CXX14_CONSTEXPR
BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
{
return opt.get_value_or(v) ;
}
template<class T>
inline BOOST_CXX14_CONSTEXPR
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
{
return opt.get_value_or(v) ;
}
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
// No-throw
template<class T>
inline BOOST_CXX14_CONSTEXPR
BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
get_pointer ( optional<T> const& opt )
{
return opt.get_ptr() ;
}
template<class T>
inline BOOST_CXX14_CONSTEXPR
BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
get_pointer ( optional<T>& opt )
{
return opt.get_ptr() ;
}
} // namespace boost
#endif // BOOST_OPTIONAL_DETAIL_OPTIONAL_NONMEMBER_INTERFACE_01FEB2026_HPP
@@ -13,9 +13,21 @@
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_REFERENCE_SPEC_AJK_03OCT2015_HPP
#ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT
#ifndef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_const.hpp>
#endif
#endif
#ifdef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
# define BOOST_OPTIONAL_TT_PREFIX ::std
#else
# define BOOST_OPTIONAL_TT_PREFIX boost
# define BOOST_OPTIONAL_REQUIRES(...) BOOST_DEDUCED_TYPENAME boost::enable_if_c<__VA_ARGS__::value, bool>::type = false
#endif
# define BOOST_OPTIONAL_TT_TYPE(...) BOOST_DEDUCED_TYPENAME BOOST_OPTIONAL_TT_PREFIX::__VA_ARGS__::type
# define BOOST_OPTIONAL_TT_PRED(...) BOOST_OPTIONAL_TT_PREFIX::__VA_ARGS__::value
# if 1
@@ -29,17 +41,17 @@ template <class From>
void prevent_binding_rvalue()
{
#ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES
static_assert(boost::is_lvalue_reference<From>::value,
static_assert(BOOST_OPTIONAL_TT_PRED(is_lvalue_reference<From>),
"binding rvalue references to optional lvalue references is disallowed");
#endif
}
template <class T>
BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type& forward_reference(T&& r)
BOOST_OPTIONAL_TT_TYPE(remove_reference<T>)& forward_reference(T&& r)
{
static_assert(boost::is_lvalue_reference<T>::value,
static_assert(BOOST_OPTIONAL_TT_PRED(is_lvalue_reference<T>),
"binding rvalue references to optional lvalue references is disallowed");
return optional_detail::forward<T>(r);
return optional_detail::forward_<T>(r);
}
#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
@@ -48,14 +60,14 @@ BOOST_DEDUCED_TYPENAME boost::remove_reference<T>::type& forward_reference(T&& r
template <class T>
struct is_const_integral
{
static const bool value = boost::is_const<T>::value && boost::is_integral<T>::value;
static const bool value = BOOST_OPTIONAL_TT_PRED(is_const<T>) && BOOST_OPTIONAL_TT_PRED(is_integral<T>);
};
template <class T>
struct is_const_integral_bad_for_conversion
{
#if (!defined BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES) && (defined BOOST_OPTIONAL_CONFIG_NO_PROPER_CONVERT_FROM_CONST_INT)
static const bool value = boost::is_const<T>::value && boost::is_integral<T>::value;
static const bool value = is_const_integral<T>::value;
#else
static const bool value = false;
#endif
@@ -90,15 +102,15 @@ struct is_optional_< ::boost::optional<U> >
template <class T>
struct is_no_optional
{
static const bool value = !is_optional_<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>::value;
static const bool value = !is_optional_<BOOST_OPTIONAL_DECAY(T)>::value;
};
template <class T, class U>
struct is_same_decayed
{
static const bool value = ::boost::is_same<T, BOOST_DEDUCED_TYPENAME ::boost::remove_reference<U>::type>::value
|| ::boost::is_same<T, const BOOST_DEDUCED_TYPENAME ::boost::remove_reference<U>::type>::value;
static const bool value = BOOST_OPTIONAL_TT_PRED(is_same<T, BOOST_OPTIONAL_TT_TYPE(remove_reference<U>)>)
|| BOOST_OPTIONAL_TT_PRED(is_same<T, const BOOST_OPTIONAL_TT_TYPE(remove_reference<U>)>);
};
template <class T, class U>
@@ -123,152 +135,165 @@ public:
typedef T* pointer_type;
typedef T* pointer_const_type;
optional() BOOST_NOEXCEPT : ptr_() {}
optional(none_t) BOOST_NOEXCEPT : ptr_() {}
BOOST_CONSTEXPR optional() BOOST_NOEXCEPT : ptr_() {}
BOOST_CONSTEXPR optional(none_t) BOOST_NOEXCEPT : ptr_() {}
template <class U>
explicit optional(const optional<U&>& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {}
optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {}
BOOST_CONSTEXPR explicit optional(const optional<U&>& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {}
BOOST_CONSTEXPR optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {}
// the following two implement a 'conditionally explicit' constructor: condition is a hack for buggy compilers with screwed conversion construction from const int
template <class U,
BOOST_OPTIONAL_REQUIRES(detail::is_same_decayed<T, U>),
BOOST_OPTIONAL_REQUIRES(detail::is_const_integral_bad_for_conversion<U>)>
BOOST_CONSTEXPR explicit
optional(U& rhs) BOOST_NOEXCEPT
: ptr_(boost::addressof(rhs)) {}
template <class U,
BOOST_OPTIONAL_REQUIRES(detail::is_same_decayed<T, U>),
BOOST_OPTIONAL_REQUIRES(!detail::is_const_integral_bad_for_conversion<U>)>
BOOST_CONSTEXPR
optional(U& rhs) BOOST_NOEXCEPT
: ptr_(boost::addressof(rhs)) {}
BOOST_CXX14_CONSTEXPR optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; }
template <class U>
explicit optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c<detail::is_same_decayed<T, U>::value && detail::is_const_integral_bad_for_conversion<U>::value, bool>::type = true) BOOST_NOEXCEPT
: ptr_(boost::addressof(rhs)) {}
template <class U>
optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c<detail::is_same_decayed<T, U>::value && !detail::is_const_integral_bad_for_conversion<U>::value, bool>::type = true) BOOST_NOEXCEPT
: ptr_(boost::addressof(rhs)) {}
optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; }
template <class U>
optional& operator=(const optional<U&>& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; }
optional& operator=(none_t) BOOST_NOEXCEPT { ptr_ = 0; return *this; }
BOOST_CXX14_CONSTEXPR optional& operator=(const optional<U&>& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; }
BOOST_CXX14_CONSTEXPR optional& operator=(none_t) BOOST_NOEXCEPT { ptr_ = 0; return *this; }
void swap(optional& rhs) BOOST_NOEXCEPT { std::swap(ptr_, rhs.ptr_); }
T& get() const { BOOST_ASSERT(ptr_); return *ptr_; }
BOOST_CXX14_CONSTEXPR void swap(optional& rhs) BOOST_NOEXCEPT { ::std::swap(ptr_, rhs.ptr_); }
constexpr T& get() const { return BOOST_OPTIONAL_ASSERTED_EXPRESSION(ptr_, *ptr_); }
T* get_ptr() const BOOST_NOEXCEPT { return ptr_; }
T* operator->() const { BOOST_ASSERT(ptr_); return ptr_; }
T& operator*() const { BOOST_ASSERT(ptr_); return *ptr_; }
constexpr T* get_ptr() const BOOST_NOEXCEPT { return ptr_; }
constexpr T* operator->() const { return BOOST_OPTIONAL_ASSERTED_EXPRESSION(ptr_, ptr_); }
constexpr T& operator*() const { return BOOST_OPTIONAL_ASSERTED_EXPRESSION(ptr_, *ptr_); }
T& value() const
constexpr T& value() const
{
if (this->is_initialized())
return this->get();
else
throw_exception(bad_optional_access());
return this->is_initialized() ?
this->get() :
(boost::throw_exception(boost::bad_optional_access()), this->get());
}
explicit operator bool() const BOOST_NOEXCEPT { return ptr_ != 0; }
constexpr explicit operator bool() const BOOST_NOEXCEPT { return ptr_ != 0; }
void reset() BOOST_NOEXCEPT { ptr_ = 0; }
BOOST_CXX14_CONSTEXPR void reset() BOOST_NOEXCEPT { ptr_ = 0; }
bool is_initialized() const BOOST_NOEXCEPT { return ptr_ != 0; }
bool has_value() const BOOST_NOEXCEPT { return ptr_ != 0; }
constexpr bool is_initialized() const BOOST_NOEXCEPT { return ptr_ != 0; }
constexpr bool has_value() const BOOST_NOEXCEPT { return ptr_ != 0; }
template <typename F>
optional<typename optional_detail::result_of<F, reference_const_type>::type>
constexpr optional<typename optional_detail::result_of<F, reference_const_type>::type>
map(F f) const
{
if (this->has_value())
return f(this->get());
else
return none;
return this->has_value() ?
f(get()) :
optional<typename optional_detail::result_of<F, reference_const_type>::type>();
}
template <typename F>
optional<typename optional_detail::result_value_type<F, reference_const_type>::type>
constexpr optional<typename optional_detail::result_value_type<F, reference_const_type>::type>
flat_map(F f) const
{
if (this->has_value())
return f(get());
else
return none;
return this->has_value() ?
f(get()) :
optional<typename optional_detail::result_value_type<F, reference_const_type>::type>();
}
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
optional(T&& /* rhs */) BOOST_NOEXCEPT { detail::prevent_binding_rvalue<T&&>(); }
template <class R>
optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::no_unboxing_cond<T, R>, bool>::type = true) BOOST_NOEXCEPT
template <class R, BOOST_OPTIONAL_REQUIRES(detail::no_unboxing_cond<T, R>)>
BOOST_CXX14_CONSTEXPR optional(R&& r) BOOST_NOEXCEPT
: ptr_(boost::addressof(r)) { detail::prevent_binding_rvalue<R>(); }
template <class R>
optional(bool cond, R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) BOOST_NOEXCEPT
template <class R, BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<R>)>
BOOST_CXX14_CONSTEXPR optional(bool cond, R&& r) BOOST_NOEXCEPT
: ptr_(cond ? boost::addressof(r) : 0) { detail::prevent_binding_rvalue<R>(); }
template <class R>
BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, optional<T&>&>::type
template <class R, BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<R>)>
BOOST_CXX14_CONSTEXPR optional<T&>&
operator=(R&& r) BOOST_NOEXCEPT { detail::prevent_binding_rvalue<R>(); ptr_ = boost::addressof(r); return *this; }
template <class R>
void emplace(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) BOOST_NOEXCEPT
template <class R, BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<R>)>
BOOST_CXX14_CONSTEXPR void emplace(R&& r) BOOST_NOEXCEPT
{ detail::prevent_binding_rvalue<R>(); ptr_ = boost::addressof(r); }
template <class R>
T& get_value_or(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) const BOOST_NOEXCEPT
template <class R, BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<R>)>
BOOST_CXX14_CONSTEXPR T& get_value_or(R&& r) const BOOST_NOEXCEPT
{ detail::prevent_binding_rvalue<R>(); return ptr_ ? *ptr_ : r; }
template <class R>
T& value_or(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) const BOOST_NOEXCEPT
template <class R, BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<R>)>
BOOST_CXX14_CONSTEXPR T& value_or(R&& r) const BOOST_NOEXCEPT
{ detail::prevent_binding_rvalue<R>(); return ptr_ ? *ptr_ : r; }
template <class R>
void reset(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<R>, bool>::type = true) BOOST_NOEXCEPT
template <class R, BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<R>)>
BOOST_CXX14_CONSTEXPR void reset(R&& r) BOOST_NOEXCEPT
{ detail::prevent_binding_rvalue<R>(); ptr_ = boost::addressof(r); }
template <class F>
T& value_or_eval(F f) const { return ptr_ ? *ptr_ : detail::forward_reference(f()); }
BOOST_CXX14_CONSTEXPR T& value_or_eval(F f) const { return ptr_ ? *ptr_ : detail::forward_reference(f()); }
#else // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
// the following two implement a 'conditionally explicit' constructor
template <class U>
explicit optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if_c<detail::no_unboxing_cond<T, U>::value && detail::is_const_integral_bad_for_conversion<U>::value, bool>::type = true) BOOST_NOEXCEPT
template <class U,
BOOST_OPTIONAL_REQUIRES(detail::no_unboxing_cond<T, U>),
BOOST_OPTIONAL_REQUIRES(detail::is_const_integral_bad_for_conversion<U>)>
BOOST_CXX14_CONSTEXPR explicit optional(U& v) BOOST_NOEXCEPT
: ptr_(boost::addressof(v)) { }
template <class U>
optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if_c<detail::no_unboxing_cond<T, U>::value && !detail::is_const_integral_bad_for_conversion<U>::value, bool>::type = true) BOOST_NOEXCEPT
template <class U,
BOOST_OPTIONAL_REQUIRES(detail::no_unboxing_cond<T, U>),
BOOST_OPTIONAL_REQUIRES(!detail::is_const_integral_bad_for_conversion<U>)>
BOOST_CXX14_CONSTEXPR optional(U& v) BOOST_NOEXCEPT
: ptr_(boost::addressof(v)) { }
template <class U>
optional(bool cond, U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) BOOST_NOEXCEPT : ptr_(cond ? boost::addressof(v) : 0) {}
template <class U,
BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<U>)>
BOOST_CXX14_CONSTEXPR optional(bool cond, U& v) BOOST_NOEXCEPT : ptr_(cond ? boost::addressof(v) : 0) {}
template <class U>
BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, optional<T&>&>::type
operator=(U& v) BOOST_NOEXCEPT
template <class U,
BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<U>)>
BOOST_CXX14_CONSTEXPR
optional<T&>& operator=(U& v) BOOST_NOEXCEPT
{
detail::prevent_assignment_from_false_const_integral<U>();
ptr_ = boost::addressof(v); return *this;
}
template <class U>
void emplace(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) BOOST_NOEXCEPT
template <class U,
BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<U>)>
BOOST_CXX14_CONSTEXPR void emplace(U& v) BOOST_NOEXCEPT
{ ptr_ = boost::addressof(v); }
template <class U>
T& get_value_or(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) const BOOST_NOEXCEPT
template <class U,
BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<U>)>
BOOST_CXX14_CONSTEXPR T& get_value_or(U& v) const BOOST_NOEXCEPT
{ return ptr_ ? *ptr_ : v; }
template <class U>
T& value_or(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) const BOOST_NOEXCEPT
{ return ptr_ ? *ptr_ : v; }
template <class U,
BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<U>)>
BOOST_CXX14_CONSTEXPR T& value_or(U& v) const BOOST_NOEXCEPT
{ return ptr_ ? *ptr_ : v; }
template <class U>
void reset(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if<detail::is_no_optional<U>, bool>::type = true) BOOST_NOEXCEPT
template <class U,
BOOST_OPTIONAL_REQUIRES(detail::is_no_optional<U>)>
BOOST_CXX14_CONSTEXPR void reset(U& v) BOOST_NOEXCEPT
{ ptr_ = boost::addressof(v); }
template <class F>
T& value_or_eval(F f) const { return ptr_ ? *ptr_ : f(); }
BOOST_CXX14_CONSTEXPR T& value_or_eval(F f) const { return ptr_ ? *ptr_ : f(); }
#endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
};
template <class T>
void swap ( optional<T&>& x, optional<T&>& y) BOOST_NOEXCEPT
BOOST_CXX14_CONSTEXPR void swap ( optional<T&>& x, optional<T&>& y) BOOST_NOEXCEPT
{
x.swap(y);
}
@@ -1,5 +1,5 @@
// Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal.
// Copyright (C) 2015, 2024 Andrzej Krzemienski.
// Copyright (C) 2015, 2024, 2026 Andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
@@ -25,32 +25,32 @@ namespace boost {
//
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator == ( optional<T> const& x, optional<T> const& y )
{ return bool(x) && bool(y) ? *x == *y : bool(x) == bool(y); }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator < ( optional<T> const& x, optional<T> const& y )
{ return !y ? false : (!x ? true : (*x) < (*y)); }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator != ( optional<T> const& x, optional<T> const& y )
{ return !( x == y ) ; }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator > ( optional<T> const& x, optional<T> const& y )
{ return y < x ; }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator <= ( optional<T> const& x, optional<T> const& y )
{ return !( y < x ) ; }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator >= ( optional<T> const& x, optional<T> const& y )
{ return !( x < y ) ; }
@@ -59,32 +59,32 @@ bool operator >= ( optional<T> const& x, optional<T> const& y )
// optional<T> vs T cases
//
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator == ( optional<T> const& x, T const& y )
{ return x && (*x == y); }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator < ( optional<T> const& x, T const& y )
{ return (!x) || (*x < y); }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator != ( optional<T> const& x, T const& y )
{ return !( x == y ) ; }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator > ( optional<T> const& x, T const& y )
{ return y < x ; }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator <= ( optional<T> const& x, T const& y )
{ return !( y < x ) ; }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator >= ( optional<T> const& x, T const& y )
{ return !( x < y ) ; }
@@ -93,32 +93,32 @@ bool operator >= ( optional<T> const& x, T const& y )
//
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator == ( T const& x, optional<T> const& y )
{ return y && (x == *y); }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator < ( T const& x, optional<T> const& y )
{ return y && (x < *y); }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator != ( T const& x, optional<T> const& y )
{ return !( x == y ) ; }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator > ( T const& x, optional<T> const& y )
{ return y < x ; }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator <= ( T const& x, optional<T> const& y )
{ return !( y < x ) ; }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator >= ( T const& x, optional<T> const& y )
{ return !( x < y ) ; }
@@ -128,33 +128,33 @@ bool operator >= ( T const& x, optional<T> const& y )
//
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator == ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
{ return !x; }
template<class T>
inline
bool operator < ( optional<T> const&, none_t )
inline BOOST_CONSTEXPR
bool operator < ( optional<T> const&, none_t ) BOOST_NOEXCEPT
{ return false; }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator != ( optional<T> const& x, none_t ) BOOST_NOEXCEPT
{ return bool(x); }
template<class T>
inline
bool operator > ( optional<T> const& x, none_t y )
inline BOOST_CONSTEXPR
bool operator > ( optional<T> const& x, none_t y ) BOOST_NOEXCEPT
{ return y < x ; }
template<class T>
inline
bool operator <= ( optional<T> const& x, none_t y )
inline BOOST_CONSTEXPR
bool operator <= ( optional<T> const& x, none_t y ) BOOST_NOEXCEPT
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( optional<T> const& x, none_t y )
inline BOOST_CONSTEXPR
bool operator >= ( optional<T> const& x, none_t y ) BOOST_NOEXCEPT
{ return !( x < y ) ; }
//
@@ -162,33 +162,33 @@ bool operator >= ( optional<T> const& x, none_t y )
//
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator == ( none_t , optional<T> const& y ) BOOST_NOEXCEPT
{ return !y; }
template<class T>
inline
bool operator < ( none_t , optional<T> const& y )
inline BOOST_CONSTEXPR
bool operator < ( none_t , optional<T> const& y ) BOOST_NOEXCEPT
{ return bool(y); }
template<class T>
inline
inline BOOST_CONSTEXPR
bool operator != ( none_t, optional<T> const& y ) BOOST_NOEXCEPT
{ return bool(y); }
template<class T>
inline
bool operator > ( none_t x, optional<T> const& y )
inline BOOST_CONSTEXPR
bool operator > ( none_t x, optional<T> const& y ) BOOST_NOEXCEPT
{ return y < x ; }
template<class T>
inline
bool operator <= ( none_t x, optional<T> const& y )
inline BOOST_CONSTEXPR
bool operator <= ( none_t x, optional<T> const& y ) BOOST_NOEXCEPT
{ return !( y < x ) ; }
template<class T>
inline
bool operator >= ( none_t x, optional<T> const& y )
inline BOOST_CONSTEXPR
bool operator >= ( none_t x, optional<T> const& y ) BOOST_NOEXCEPT
{ return !( x < y ) ; }
} // namespace boost
@@ -0,0 +1,36 @@
// Copyright (C) 2026 Andrzej Krzemieński.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
//
//
// This header provides definitions required by any specialization of
// optional<>.
#ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_SELECT_IMPLEMENTATION_01FEB2026_HPP
#define BOOST_OPTIONAL_DETAIL_OPTIONAL_SELECT_IMPLEMENTATION_01FEB2026_HPP
#include <boost/config.hpp>
#if !defined(BOOST_NO_CXX11_CONSTEXPR) && \
!defined(BOOST_NO_CXX11_REF_QUALIFIERS) && \
!defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \
!defined(BOOST_NO_CXX11_UNRESTRICTED_UNION) && \
!defined(BOOST_NO_CXX11_NOEXCEPT) && \
!defined(BOOST_NO_CXX11_DEFAULTED_MOVES)
# define BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
#endif
// In C++20 we have `std::construct_at()` which is a constexpr equivalent of
// placement-new. We can then make more functions constexpr.
// TBD: This additional constexpr-ication is left for the future.
# define BOOST_OPTIONAL_CXX20_CONSTEXPR
#endif //BOOST_OPTIONAL_DETAIL_OPTIONAL_SELECT_IMPLEMENTATION_01FEB2026_HPP
@@ -54,7 +54,7 @@ struct swap_selector<true>
#endif
#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
# define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) optional_detail::move(EXPR_)
# define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) optional_detail::move_(EXPR_)
#else
# define BOOST_OPTIONAL_DETAIL_MOVE(EXPR_) EXPR_
#endif
@@ -54,7 +54,7 @@ class tc_optional_base : public optional_tag
:
m_initialized(false)
{
construct(optional_detail::forward<Expr>(expr),tag);
construct(optional_detail::forward_<Expr>(expr),tag);
}
// tc_optional_base& operator= ( tc_optional_base const& ) = default;
@@ -102,7 +102,7 @@ class tc_optional_base : public optional_tag
template<class Expr, class ExprPtr>
void assign_expr ( Expr&& expr, ExprPtr const* tag )
{
construct(optional_detail::forward<Expr>(expr),tag);
construct(optional_detail::forward_<Expr>(expr),tag);
}
#endif
@@ -138,14 +138,14 @@ class tc_optional_base : public optional_tag
template<class... Args>
void construct ( in_place_init_t, Args&&... args )
{
m_storage = value_type( optional_detail::forward<Args>(args)... ) ;
m_storage = value_type( optional_detail::forward_<Args>(args)... ) ;
m_initialized = true ;
}
template<class... Args>
void emplace_assign ( Args&&... args )
{
construct(in_place_init, optional_detail::forward<Args>(args)...);
construct(in_place_init, optional_detail::forward_<Args>(args)...);
}
template<class... Args>
@@ -153,7 +153,7 @@ class tc_optional_base : public optional_tag
:
m_initialized(false)
{
construct(in_place_init, optional_detail::forward<Args>(args)...);
construct(in_place_init, optional_detail::forward_<Args>(args)...);
}
template<class... Args>
@@ -162,7 +162,7 @@ class tc_optional_base : public optional_tag
m_initialized(false)
{
if ( cond )
construct(in_place_init, optional_detail::forward<Args>(args)...);
construct(in_place_init, optional_detail::forward_<Args>(args)...);
}
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
@@ -207,7 +207,7 @@ class tc_optional_base : public optional_tag
template<class Expr>
void construct ( Expr&& expr, void const* )
{
m_storage = value_type(optional_detail::forward<Expr>(expr)) ;
m_storage = value_type(optional_detail::forward_<Expr>(expr)) ;
m_initialized = true ;
}
@@ -218,7 +218,7 @@ class tc_optional_base : public optional_tag
template<class Expr>
void assign_expr_to_initialized ( Expr&& expr, void const* )
{
assign_value( optional_detail::forward<Expr>(expr) );
assign_value( optional_detail::forward_<Expr>(expr) );
}
#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
@@ -1,41 +0,0 @@
// Copyright (C) 2024 Ryan Malcolm Underwood.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// typenametea@gmail.com
#ifndef BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_UTILITY_RMU_06OCT2024_HPP
#define BOOST_OPTIONAL_OPTIONAL_DETAIL_OPTIONAL_UTILITY_RMU_06OCT2024_HPP
namespace boost {
namespace optional_detail {
// Workaround: forward and move aren't constexpr in C++11
template <class T>
inline constexpr T&& forward(typename boost::remove_reference<T>::type& t) noexcept
{
return static_cast<T&&>(t);
}
template <class T>
inline constexpr T&& forward(typename boost::remove_reference<T>::type&& t) noexcept
{
static_assert(!boost::is_lvalue_reference<T>::value, "Can not forward an rvalue as an lvalue.");
return static_cast<T&&>(t);
}
template <class T>
inline constexpr typename boost::remove_reference<T>::type&& move(T&& t) noexcept
{
return static_cast<typename boost::remove_reference<T>::type&&>(t);
}
} // namespace optional_detail
} // namespace boost
#endif
@@ -0,0 +1,722 @@
// Copyright (C) 2026 Andrzej Krzemieński.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
//
//
// This header provides definitions required by any specialization of
// optional<>.
#ifndef BOOST_OPTIONAL_DETAIL_UNION_OPTIONAL_01FEB2026_HPP
#define BOOST_OPTIONAL_DETAIL_UNION_OPTIONAL_01FEB2026_HPP
//#include <initializer_list>
#include <boost/assert.hpp>
#include <boost/core/invoke_swap.hpp>
#include <boost/throw_exception.hpp>
#include <boost/optional/bad_optional_access.hpp>
// This macro shall be put in the position of a template parameter.
// It emulates the requires clause.
# define BOOST_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false
# ifdef __cpp_guaranteed_copy_elision
# if __cpp_guaranteed_copy_elision
# define BOOST_OPTIONAL_CONSTEXPR_COPY
# endif
# endif
template <typename T, typename U>
struct fail_hard_on_nonconvertible
{
static_assert(::std::is_convertible<U&&, T>::value, "The argument must be convertible to T");
using type = bool;
};
// Missing C++17 type traits
namespace boost { namespace optional_detail {
template <class...>
struct conjunction : ::std::true_type {};
template <class B1>
struct conjunction<B1> : B1 {};
template <class B1, class... Bn>
struct conjunction<B1, Bn...>
: ::std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
}}
namespace boost { namespace optional_detail {
// Tag to indicate a special-purpose constructor
BOOST_INLINE_VARIABLE constexpr struct trivial_init_t{} trivial_init{};
template <class T>
union constexpr_union_storage_t
{
static_assert(::std::is_trivially_destructible<T>::value, "!!");
unsigned char dummy_;
T value_;
constexpr constexpr_union_storage_t( trivial_init_t ) noexcept : dummy_() {};
#if defined(BOOST_GCC) && (__GNUC__ >= 7)
// false positive, see https://github.com/boostorg/variant2/issues/55,
// https://github.com/boostorg/url/issues/979
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
template <class... Args>
constexpr constexpr_union_storage_t( Args&&... args ) : value_(forward_<Args>(args)...) {}
#if defined(BOOST_GCC) && (__GNUC__ >= 7)
# pragma GCC diagnostic pop
#endif
//~constexpr_union_storage_t() = default; // No need to destroy a trivially-destructible type
};
template <class T>
union fallback_union_storage_t
{
unsigned char dummy_;
T value_;
constexpr fallback_union_storage_t( trivial_init_t ) noexcept : dummy_() {};
#if defined(BOOST_GCC) && (__GNUC__ >= 7)
// false positive, see https://github.com/boostorg/variant2/issues/55,
// https://github.com/boostorg/url/issues/979
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
template <class... Args>
constexpr fallback_union_storage_t( Args&&... args ) : value_(forward_<Args>(args)...) {}
#if defined(BOOST_GCC) && (__GNUC__ >= 7)
# pragma GCC diagnostic pop
#endif
~fallback_union_storage_t(){} // My owner will destroy the `T` if needed.
// Cannot default in a union with nontrivial `T`.
};
// `guarded_storage` is a union + a flag indicating if a `T` has been initialized.
// this way the destructor knows if it should destroy the `T`.
template <class T>
struct constexpr_guarded_storage
{
static_assert(::std::is_trivially_destructible<T>::value, "!!");
bool init_;
constexpr_union_storage_t<T> storage_;
constexpr constexpr_guarded_storage() noexcept : init_(false), storage_(trivial_init) {};
explicit constexpr constexpr_guarded_storage(const T& v) : init_(true), storage_(v) {}
explicit constexpr constexpr_guarded_storage(T&& v) : init_(true), storage_(move_(v)) {}
template <class... Args> explicit constexpr constexpr_guarded_storage(optional_ns::in_place_init_t, Args&&... args)
: init_(true), storage_(forward_<Args>(args)...) {}
// template <class U, class... Args, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
// constexpr explicit constexpr_guarded_storage(optional_ns::in_place_init_t, ::std::initializer_list<U> il, Args&&... args)
// : init_(true), storage_(il, forward_<Args>(args)...) {}
BOOST_CXX14_CONSTEXPR void reset () noexcept { init_ = false; }
//~constexpr_guarded_storage() = default;
#if (defined(_MSC_VER) && 1910 <= _MSC_VER && _MSC_VER <= 1916)
// Workaround for MSVC 14.1x bug where it eagerly tries to define the copy/move operations
// these are declared but never defined
constexpr_guarded_storage(const constexpr_guarded_storage&);
constexpr_guarded_storage(constexpr_guarded_storage&&);
constexpr_guarded_storage& operator=(const constexpr_guarded_storage&);
constexpr_guarded_storage& operator=(constexpr_guarded_storage&&);
#endif
};
template <class T>
struct fallback_guarded_storage
{
bool init_;
fallback_union_storage_t<T> storage_;
constexpr fallback_guarded_storage() noexcept : init_(false), storage_(trivial_init) {};
explicit constexpr fallback_guarded_storage(const T& v) : init_(true), storage_(v) {}
explicit constexpr fallback_guarded_storage(T&& v) : init_(true), storage_(move_(v)) {}
template <class... Args> explicit constexpr fallback_guarded_storage(optional_ns::in_place_init_t, Args&&... args)
: init_(true), storage_(forward_<Args>(args)...) {}
// template <class U, class... Args, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
// explicit fallback_guarded_storage(optional_ns::in_place_init_t, ::std::initializer_list<U> il, Args&&... args)
// : init_(true), storage_(il, forward_<Args>(args)...) {}
void reset() noexcept
{
if (init_)
{
storage_.value_.T::~T();
init_ = false;
}
}
~fallback_guarded_storage() { if (init_) storage_.value_.T::~T(); }
#if (defined(_MSC_VER) && 1910 <= _MSC_VER && _MSC_VER <= 1916)
// Workaround for MSVC 14.1x bug where it eagerly tries to define the copy/move operations
// These are declared but never defined
fallback_guarded_storage(const fallback_guarded_storage&);
fallback_guarded_storage(fallback_guarded_storage&&);
fallback_guarded_storage& operator=(const fallback_guarded_storage&);
fallback_guarded_storage& operator=(fallback_guarded_storage&&);
#endif
};
template <class T>
using guarded_storage = typename ::std::conditional<
::std::is_trivially_destructible<T>::value, // if possible
constexpr_guarded_storage<typename ::std::remove_const<T>::type>, // use storage with trivial destructor
fallback_guarded_storage<typename ::std::remove_const<T>::type>
>::type;
}}
namespace boost {
template <class T>
class optional : public optional_detail::optional_tag
{
using storage_t = optional_detail::guarded_storage<T>;
storage_t storage;
static_assert( !::std::is_same<typename std::decay<T>::type, none_t>::value, "optional<none_t> is illegal" );
static_assert( !::std::is_same<typename std::decay<T>::type, in_place_init_t>::value, "optional<in_place_init_t> is illegal" );
static_assert( !::std::is_same<typename std::decay<T>::type, in_place_init_if_t>::value, "optional<in_place_init_if_t> is illegal" );
BOOST_CXX14_CONSTEXPR typename ::std::remove_const<T>::type* dataptr() { return ::boost::addressof(storage.storage_.value_); }
constexpr const T* dataptr() const { return ::boost::addressof(storage.storage_.value_); }
constexpr const T& contained_val() const& { return storage.storage_.value_; }
BOOST_CXX14_CONSTEXPR T&& contained_val() && { return optional_detail::move_(storage.storage_.value_); }
BOOST_CXX14_CONSTEXPR T& contained_val() & { return storage.storage_.value_; }
template <typename... Args>
BOOST_OPTIONAL_CXX20_CONSTEXPR void initialize(Args&&... args)
{
BOOST_ASSERT(!storage.init_);
::new (static_cast<void*>(dataptr())) T(optional_detail::forward_<Args>(args)...);
storage.init_ = true;
}
#ifdef BOOST_OPTIONAL_CONSTEXPR_COPY
// The conditional initialization of storage needs to employ a factory
// function, so that we can utilize the guaranteed copy elision on the
// return type.
// an alternative -- using a conditional operator in the initializer --
// does not work in MSVC 14.2 and 14.3.
template <typename... U>
static constexpr storage_t conditional_storage_from_values(bool cond, U&&... v)
{
if (cond)
return storage_t(in_place_init, optional_detail::forward_<U>(v)...);
else
return storage_t();
}
template <typename OU>
static constexpr storage_t conditional_storage_from_optional(OU&& ou)
{
if (ou.has_value())
return storage_t(in_place_init, *optional_detail::forward_<OU>(ou));
else
return storage_t();
}
#endif
public:
using value_type = T;
using unqualified_value_type = typename ::std::remove_const<T>::type;
using reference_type = T&;
using reference_const_type = T const&;
using argument_type = T const&;
using rval_reference_type = T&&;
using reference_type_of_temporary_wrapper = T&&;
using pointer_type = T*;
using pointer_const_type = T const*;
constexpr bool is_initialized() const noexcept { return storage.init_; }
constexpr optional() noexcept : storage() {};
constexpr optional(none_t) noexcept : storage() {};
constexpr optional(const T& v) : storage(v) {}
constexpr optional(T&& v) : storage(optional_detail::move_(v)) {}
#ifdef BOOST_OPTIONAL_CONSTEXPR_COPY
constexpr optional(bool cond, const T& v)
: storage(conditional_storage_from_values(cond, v))
{}
constexpr optional(bool cond, T&& v)
: storage(conditional_storage_from_values(cond, optional_detail::move_(v)))
{}
constexpr optional(const optional& rhs)
: storage(conditional_storage_from_optional(rhs))
{}
constexpr optional(optional&& rhs)
noexcept(::std::is_nothrow_move_constructible<T>::value)
: storage(conditional_storage_from_optional(optional_detail::move_(rhs)))
{}
template <typename U, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U const&>)>
constexpr explicit optional(optional<U> const& rhs)
: storage(conditional_storage_from_optional(rhs))
{}
template <typename U, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U&&>)>
constexpr explicit optional(optional<U> && rhs)
: storage(conditional_storage_from_optional(optional_detail::move_(rhs)))
{}
template <typename... Args>
constexpr explicit optional( in_place_init_if_t, bool cond, Args&&... args )
: storage(conditional_storage_from_values(cond, optional_detail::forward_<Args>(args)...))
{}
#else
optional(bool cond, const T& v)
: storage()
{
if (cond)
initialize(v);
}
optional(bool cond, T&& v)
: storage()
{
if (cond)
initialize(optional_detail::move_(v));
}
optional(const optional& rhs)
: storage()
{
if (rhs.is_initialized())
initialize(*rhs);
}
optional(optional&& rhs)
noexcept(::std::is_nothrow_move_constructible<T>::value)
: storage()
{
if (rhs.is_initialized())
initialize(*optional_detail::move_(rhs));
}
template <typename U, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U const&>)>
explicit optional(optional<U> const& rhs)
: storage()
{
if (rhs.is_initialized())
initialize(*rhs);
}
template <typename U, BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U&&>)>
explicit optional(optional<U> && rhs)
: storage()
{
if (rhs.is_initialized())
initialize(*optional_detail::move_(rhs));
}
template <typename... Args>
explicit optional( in_place_init_if_t, bool cond, Args&&... args )
: storage()
{
if (cond)
initialize(optional_detail::forward_<Args>(args)...);
}
#endif // BOOST_OPTIONAL_CONSTEXPR_COPY
template <typename FT,
BOOST_OPTIONAL_REQUIRES(optional_detail::is_typed_in_place_factory<FT>)>
/*non-constexpr (deprecated)*/
explicit optional (FT&& factory)
: storage()
{
factory.apply(this->dataptr());
storage.init_ = true ;
}
template <typename FT,
BOOST_OPTIONAL_REQUIRES(optional_detail::is_in_place_factory<FT>)>
/*non-constexpr (deprecated)*/
explicit optional (FT&& factory)
: storage()
{
boost_optional_detail::construct<value_type>(factory, this->dataptr());
storage.init_ = true;
}
template <typename U,
BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U&&>),
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_typed_in_place_factory<U>),
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_in_place_factory<U>)>
constexpr explicit optional(U&& v)
: storage(optional_ns::in_place_init, optional_detail::forward_<U>(v))
{}
template <typename... Args>
constexpr explicit optional( in_place_init_t, Args&&... args )
: storage(in_place_init, optional_detail::forward_<Args>(args)...)
{}
BOOST_CXX14_CONSTEXPR operator optional<T&>() & noexcept
{
return this->has_value() ? optional<T&>(**this) : optional<T&>();
}
BOOST_CONSTEXPR operator optional<const T&>() const& noexcept
{
return this->has_value() ? optional<const T&>(**this) : optional<const T&>();
}
BOOST_CXX14_CONSTEXPR operator optional<T&>() && noexcept = delete;
BOOST_CONSTEXPR operator optional<const T&>() const&& noexcept = delete;
BOOST_CXX14_CONSTEXPR void reset() noexcept
{
storage.reset();
}
BOOST_OPTIONAL_CXX20_CONSTEXPR void reset(const T& v)
{
*this = v;
}
template <typename... Args>
BOOST_OPTIONAL_CXX20_CONSTEXPR void emplace(Args&&... args)
{
reset();
// <-- now we are not containing a value
initialize(optional_detail::forward_<Args>(args)...);
}
BOOST_CXX14_CONSTEXPR optional& operator=(none_t) noexcept
{
reset();
return *this;
}
BOOST_OPTIONAL_CXX20_CONSTEXPR optional& operator=(const optional& rhs)
{
if (has_value())
{
if (rhs.has_value())
**this = *rhs;
else
reset();
}
else
{
if (rhs.has_value())
initialize(*rhs);
}
return *this;
}
BOOST_OPTIONAL_CXX20_CONSTEXPR optional& operator=(optional&& rhs)
noexcept(::std::is_nothrow_move_assignable<T>::value && ::std::is_nothrow_move_constructible<T>::value)
{
if (has_value())
{
if (rhs.has_value())
**this = *optional_detail::move_(rhs);
else
reset();
}
else
{
if (rhs.has_value())
initialize(*optional_detail::move_(rhs) );
}
return *this;
}
template <typename U>
BOOST_OPTIONAL_CXX20_CONSTEXPR optional& operator=(const optional<U>& rhs)
{
if (has_value())
{
if (rhs.has_value())
**this = *rhs;
else
reset();
}
else
{
if (rhs.has_value())
initialize(*rhs);
}
return *this;
}
template <typename U>
BOOST_OPTIONAL_CXX20_CONSTEXPR optional& operator=(optional<U>&& rhs)
{
if (has_value())
{
if (rhs.has_value())
**this = *optional_detail::move_(rhs);
else
reset();
}
else
{
if (rhs.has_value())
initialize(*optional_detail::move_(rhs));
}
return *this;
}
template <class U = typename ::std::remove_cv<T>::type,
BOOST_OPTIONAL_REQUIRES(!::std::is_same<typename ::std::decay<U>::type, optional>),
BOOST_OPTIONAL_REQUIRES(!optional_detail::conjunction<::std::is_scalar<T>, ::std::is_same<T, BOOST_OPTIONAL_DECAY(U)>>),
BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U>),
BOOST_OPTIONAL_REQUIRES(::std::is_assignable<T&, U>),
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_typed_in_place_factory<U>),
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_in_place_factory<U>)
>
BOOST_OPTIONAL_CXX20_CONSTEXPR optional& operator=(U&& v)
{
if (is_initialized())
contained_val() = optional_detail::forward_<U>(v);
else
initialize(optional_detail::forward_<U>(v));
return *this;
}
template <class F, BOOST_OPTIONAL_REQUIRES(optional_detail::is_in_place_factory<F>)>
/*non-constexpr (deprecated)*/
optional& operator=(F&& factory)
{
reset();
boost_optional_detail::construct<value_type>(factory, this->dataptr());
storage.init_ = true;
return *this;
}
template <class F, BOOST_OPTIONAL_REQUIRES(optional_detail::is_typed_in_place_factory<F>)>
/*non-constexpr (deprecated)*/
optional& operator=(F&& factory)
{
reset();
factory.apply(this->dataptr());
storage.init_ = true;
return *this;
}
BOOST_OPTIONAL_CXX20_CONSTEXPR
void swap(optional& rhs)
noexcept(::std::is_nothrow_move_constructible<T>::value && noexcept(boost::core::invoke_swap(*rhs, *rhs)))
{
if (is_initialized())
{
if (rhs.is_initialized())
boost::core::invoke_swap(contained_val(), rhs.contained_val());
else
{ rhs.initialize(optional_detail::move_(*this).contained_val()); reset(); }
}
else
{
if (rhs.is_initialized())
{ initialize(optional_detail::move_(rhs).contained_val()); rhs.reset(); }
}
}
~optional() = default; // The destructor in `storage`, based on the specialization
// will be trivial or not.
constexpr bool has_value() const noexcept { return this->is_initialized(); }
constexpr explicit operator bool() const noexcept { return this->is_initialized(); }
constexpr reference_const_type get() const { return BOOST_OPTIONAL_ASSERTED_EXPRESSION(this->is_initialized(), this->contained_val()); }
BOOST_CXX14_CONSTEXPR reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->contained_val(); }
//BOOST_DEPRECATED("use `value_or(v)` instead")
reference_const_type get_value_or (reference_const_type v) const { return this->is_initialized() ? this->contained_val() : v; }
//BOOST_DEPRECATED("use `value_or(v)` instead")
reference_type get_value_or (reference_type v) { return this->is_initialized() ? this->contained_val() : v; }
pointer_const_type get_ptr() const { return is_initialized() ? dataptr() : nullptr; }
pointer_type get_ptr() { return is_initialized() ? dataptr() : nullptr; }
constexpr reference_const_type operator*() const& { return this->get(); }
BOOST_CXX14_CONSTEXPR reference_type operator*() & { return this->get(); }
BOOST_CXX14_CONSTEXPR reference_type_of_temporary_wrapper operator*() && { return optional_detail::move_(this->get()); }
constexpr pointer_const_type operator->() const { return BOOST_OPTIONAL_ASSERTED_EXPRESSION(this->is_initialized(), this->dataptr()); }
BOOST_CXX14_CONSTEXPR pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->dataptr(); }
constexpr reference_const_type value() const&
{
return this->is_initialized() ? this->get() : (boost::throw_exception(boost::bad_optional_access()), this->get());
}
BOOST_CXX14_CONSTEXPR reference_type value() &
{
if (this->is_initialized())
return this->get();
else
boost::throw_exception(boost::bad_optional_access());
}
BOOST_CXX14_CONSTEXPR reference_type_of_temporary_wrapper value() &&
{
if (this->is_initialized())
return optional_detail::move_(this->get());
else
boost::throw_exception(boost::bad_optional_access());
}
template <class U = typename ::std::remove_cv<T>::type,
typename fail_hard_on_nonconvertible<T, U>::type = true>
constexpr value_type value_or(U&& v) const&
{
return this->is_initialized() ? get() : T(optional_detail::forward_<U>(v));
}
template <class U = typename ::std::remove_cv<T>::type>
BOOST_CXX14_CONSTEXPR value_type value_or(U&& v) &&
{
if (this->is_initialized())
return optional_detail::move_(get());
else
return optional_detail::forward_<U>(v);
}
template <typename F,
typename fail_hard_on_nonconvertible<T, decltype(optional_detail::declval_<F>()())>::type = true>
constexpr value_type value_or_eval(F f) const&
{
return this->is_initialized() ? get() : value_type(f());
}
template <typename F>
BOOST_CXX14_CONSTEXPR value_type value_or_eval ( F f ) &&
{
if (this->is_initialized())
return optional_detail::move_(get());
else
return f();
}
template <typename F>
BOOST_CXX14_CONSTEXPR optional<typename optional_detail::result_of<F, reference_type>::type>
map(F f) &
{
if (this->has_value())
return f(get());
else
return none;
}
template <typename F>
constexpr optional<typename optional_detail::result_of<F, reference_const_type>::type>
map(F f) const&
{
return this->has_value() ?
f(get()) :
optional<typename optional_detail::result_of<F, reference_const_type>::type>();
}
template <typename F>
BOOST_CXX14_CONSTEXPR optional<typename optional_detail::result_of<F, reference_type_of_temporary_wrapper>::type>
map(F f) &&
{
if (this->has_value())
return f(optional_detail::move_(this->get()));
else
return none;
}
template <typename F>
BOOST_CXX14_CONSTEXPR optional<typename optional_detail::result_value_type<F, reference_type>::type>
flat_map(F f) &
{
if (this->has_value())
return f(get());
else
return none;
}
template <typename F>
constexpr optional<typename optional_detail::result_value_type<F, reference_const_type>::type>
flat_map(F f) const&
{
return this->has_value() ?
f(get()) :
optional<typename optional_detail::result_value_type<F, reference_const_type>::type>();
}
template <typename F>
BOOST_CXX14_CONSTEXPR optional<typename optional_detail::result_value_type<F, reference_type_of_temporary_wrapper>::type>
flat_map(F f) &&
{
if (this->has_value())
return f(optional_detail::move_(get()));
else
return none;
}
};
template <typename T>
BOOST_OPTIONAL_CXX20_CONSTEXPR
void swap(optional<T>& lhs, optional<T>& rhs)
noexcept(::std::is_nothrow_move_constructible<T>::value && noexcept(boost::core::invoke_swap(*lhs, *rhs)))
{
lhs.swap(rhs);
}
}
#endif // BOOST_OPTIONAL_DETAIL_UNION_OPTIONAL_01FEB2026_HPP
+101 -228
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,18 @@
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/is_volatile.hpp>
#include <boost/type_traits/is_scalar.hpp>
#include <boost/none.hpp>
#include <boost/optional/optional_fwd.hpp>
#include <boost/optional/detail/optional_config.hpp>
#include <boost/optional/detail/optional_factory_support.hpp>
#include <boost/optional/detail/optional_aligned_storage.hpp>
#include <boost/optional/detail/optional_hash.hpp>
#include <boost/optional/detail/optional_utility.hpp>
namespace boost { namespace optional_detail {
template <typename T>
struct optional_value_type
{
};
template <typename U>
struct optional_value_type< ::boost::optional<U> >
{
typedef U type;
};
template <typename T>
T declval();
// implementing my own result_of so that it works for C++11 (std::result_of)
// and in C++20 (std::invoke_result).
template <typename F, typename Ref, typename Rslt = decltype(declval<F>()(declval<Ref>()))>
struct result_of
{
typedef Rslt type;
};
template <typename F, typename Ref, typename Rslt = typename optional_value_type<typename result_of<F, Ref>::type>::type>
struct result_value_type
{
typedef Rslt type;
};
// optional<typename optional_detail::optional_value_type<decltype(optional_detail::declval<F>()(optional_detail::declval<reference_type>()))>::type>
}} // namespace boost::optional_detail
namespace boost {
namespace optional_ns {
// a tag for in-place initialization of contained value
struct in_place_init_t
{
struct init_tag{};
BOOST_CONSTEXPR explicit in_place_init_t(init_tag){}
};
BOOST_INLINE_CONSTEXPR in_place_init_t in_place_init ((in_place_init_t::init_tag()));
// a tag for conditional in-place initialization of contained value
struct in_place_init_if_t
{
struct init_tag{};
BOOST_CONSTEXPR explicit in_place_init_if_t(init_tag){}
};
BOOST_INLINE_CONSTEXPR in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag()));
} // namespace optional_ns
using optional_ns::in_place_init_t;
using optional_ns::in_place_init;
using optional_ns::in_place_init_if_t;
using optional_ns::in_place_init_if;
namespace optional_detail {
struct init_value_tag {};
struct optional_tag {};
template<class T>
class optional_base : public optional_tag
@@ -177,7 +145,7 @@ class optional_base : public optional_tag
:
m_initialized(false)
{
construct( optional_detail::move(val) );
construct( optional_detail::move_(val) );
}
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional<T>.
@@ -197,7 +165,7 @@ class optional_base : public optional_tag
m_initialized(false)
{
if ( cond )
construct(optional_detail::move(val));
construct(optional_detail::move_(val));
}
// Creates a deep copy of another optional<T>
@@ -218,7 +186,7 @@ class optional_base : public optional_tag
m_initialized(false)
{
if ( rhs.is_initialized() )
construct( optional_detail::move(rhs.get_impl()) );
construct( optional_detail::move_(rhs.get_impl()) );
}
@@ -227,7 +195,7 @@ class optional_base : public optional_tag
:
m_initialized(false)
{
construct(optional_detail::forward<Expr>(expr),tag);
construct(optional_detail::forward_<Expr>(expr),tag);
}
optional_base& operator= ( optional_base const& rhs )
@@ -268,13 +236,13 @@ class optional_base : public optional_tag
if (is_initialized())
{
if ( rhs.is_initialized() )
assign_value( optional_detail::move(rhs.get_impl()) );
assign_value( optional_detail::move_(rhs.get_impl()) );
else destroy();
}
else
{
if ( rhs.is_initialized() )
construct(optional_detail::move(rhs.get_impl()));
construct(optional_detail::move_(rhs.get_impl()));
}
}
@@ -334,8 +302,8 @@ class optional_base : public optional_tag
void assign ( rval_reference_type val )
{
if (is_initialized())
assign_value( optional_detail::move(val) );
else construct( optional_detail::move(val) );
assign_value( optional_detail::move_(val) );
else construct( optional_detail::move_(val) );
}
// Assigns from "none", destroying the current value, if any, leaving this UNINITIALIZED
@@ -348,8 +316,8 @@ class optional_base : public optional_tag
void assign_expr ( Expr&& expr, ExprPtr const* tag )
{
if (is_initialized())
assign_expr_to_initialized(optional_detail::forward<Expr>(expr),tag);
else construct(optional_detail::forward<Expr>(expr),tag);
assign_expr_to_initialized(optional_detail::forward_<Expr>(expr),tag);
else construct(optional_detail::forward_<Expr>(expr),tag);
}
#endif
@@ -381,7 +349,7 @@ class optional_base : public optional_tag
void construct ( rval_reference_type val )
{
::new (m_storage.address()) unqualified_value_type( optional_detail::move(val) ) ;
::new (m_storage.address()) unqualified_value_type( optional_detail::move_(val) ) ;
m_initialized = true ;
}
@@ -391,7 +359,7 @@ class optional_base : public optional_tag
template<class... Args>
void construct ( in_place_init_t, Args&&... args )
{
::new (m_storage.address()) unqualified_value_type( optional_detail::forward<Args>(args)... ) ;
::new (m_storage.address()) unqualified_value_type( optional_detail::forward_<Args>(args)... ) ;
m_initialized = true ;
}
@@ -399,7 +367,7 @@ class optional_base : public optional_tag
void emplace_assign ( Args&&... args )
{
destroy();
construct(in_place_init, optional_detail::forward<Args>(args)...);
construct(in_place_init, optional_detail::forward_<Args>(args)...);
}
template<class... Args>
@@ -407,7 +375,7 @@ class optional_base : public optional_tag
:
m_initialized(false)
{
construct(in_place_init, optional_detail::forward<Args>(args)...);
construct(in_place_init, optional_detail::forward_<Args>(args)...);
}
template<class... Args>
@@ -416,7 +384,7 @@ class optional_base : public optional_tag
m_initialized(false)
{
if ( cond )
construct(in_place_init, optional_detail::forward<Args>(args)...);
construct(in_place_init, optional_detail::forward_<Args>(args)...);
}
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
@@ -461,7 +429,7 @@ class optional_base : public optional_tag
template<class Expr>
void construct ( Expr&& expr, void const* )
{
new (m_storage.address()) unqualified_value_type(optional_detail::forward<Expr>(expr)) ;
new (m_storage.address()) unqualified_value_type(optional_detail::forward_<Expr>(expr)) ;
m_initialized = true ;
}
@@ -472,7 +440,7 @@ class optional_base : public optional_tag
template<class Expr>
void assign_expr_to_initialized ( Expr&& expr, void const* )
{
assign_value( optional_detail::forward<Expr>(expr) );
assign_value( optional_detail::forward_<Expr>(expr) );
}
#ifdef BOOST_OPTIONAL_WEAK_OVERLOAD_RESOLUTION
@@ -497,7 +465,7 @@ class optional_base : public optional_tag
{
// An exception can be thrown here.
// It it happens, THIS will be left uninitialized.
new (m_storage.address()) unqualified_value_type(optional_detail::move(expr.get())) ;
new (m_storage.address()) unqualified_value_type(optional_detail::move_(expr.get())) ;
m_initialized = true ;
}
}
@@ -548,16 +516,15 @@ struct has_dedicated_constructor
{};
template <typename U>
struct is_in_place_factory
: boost::disjunction< boost::is_base_of<boost::in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>,
boost::is_base_of<boost::typed_in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type> >
struct is_factory
: boost::disjunction< is_in_place_factory<U>, is_typed_in_place_factory<U> >
{};
#if !defined(BOOST_OPTIONAL_DETAIL_NO_IS_CONSTRUCTIBLE_TRAIT)
template <typename T, typename U>
struct is_factory_or_constructible_to_T
: boost::disjunction< is_in_place_factory<U>, boost::is_constructible<T, U&&> >
: boost::disjunction< is_factory<U>, boost::is_constructible<T, U&&> >
{};
template <typename T, typename U>
@@ -597,7 +564,7 @@ struct is_opt_assignable : boost::is_convertible<U, T>
template <typename T, typename U>
struct is_factory_or_opt_assignable_to_T
: boost::disjunction< is_in_place_factory<U>, is_opt_assignable<T, U> >
: boost::disjunction< is_factory<U>, is_opt_assignable<T, U> >
{};
template <typename T, typename U, bool = has_dedicated_constructor<T, U>::value>
@@ -675,7 +642,7 @@ class optional
// Creates an optional<T> initialized with 'move(val)'.
// Can throw if T::T(T &&) does
optional ( rval_reference_type val ) : base(optional_detail::init_value_tag(), optional_detail::forward<T>(val))
optional ( rval_reference_type val ) : base(optional_detail::init_value_tag(), optional_detail::forward_<T>(val))
{}
// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
@@ -684,7 +651,7 @@ class optional
/// Creates an optional<T> initialized with 'val' IFF cond is true, otherwise creates an uninitialized optional.
// Can throw if T::T(T &&) does
optional ( bool cond, rval_reference_type val ) : base( cond, optional_detail::forward<T>(val) )
optional ( bool cond, rval_reference_type val ) : base( cond, optional_detail::forward_<T>(val) )
{}
// NOTE: MSVC needs templated versions first
@@ -718,7 +685,7 @@ class optional
base()
{
if ( rhs.is_initialized() )
this->construct( optional_detail::move(rhs.get()) );
this->construct( optional_detail::move_(rhs.get()) );
}
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
@@ -737,7 +704,7 @@ class optional
explicit optional ( Expr&& expr,
BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate<T, Expr>, bool>::type = true
)
: base(optional_detail::forward<Expr>(expr),boost::addressof(expr))
: base(optional_detail::forward_<Expr>(expr),boost::addressof(expr))
{}
#endif // !defined BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
@@ -757,7 +724,7 @@ class optional
#else
optional ( optional && rhs )
BOOST_NOEXCEPT_IF(::boost::is_nothrow_move_constructible<T>::value)
: base( optional_detail::move(rhs) )
: base( optional_detail::move_(rhs) )
{}
#endif
@@ -776,7 +743,7 @@ class optional
BOOST_DEDUCED_TYPENAME boost::enable_if<optional_detail::is_optional_val_assign_candidate<T, Expr>, optional&>::type
operator= ( Expr&& expr )
{
this->assign_expr(optional_detail::forward<Expr>(expr),boost::addressof(expr));
this->assign_expr(optional_detail::forward_<Expr>(expr),boost::addressof(expr));
return *this ;
}
@@ -798,7 +765,7 @@ class optional
template<class U>
optional& operator= ( optional<U> && rhs )
{
this->assign(optional_detail::move(rhs));
this->assign(optional_detail::move_(rhs));
return *this ;
}
@@ -834,7 +801,7 @@ class optional
BOOST_DEDUCED_TYPENAME boost::enable_if<boost::is_same<T, BOOST_DEDUCED_TYPENAME boost::decay<T_>::type>, optional&>::type
operator= ( T_&& val )
{
this->assign( optional_detail::forward<T_>(val) ) ;
this->assign( optional_detail::forward_<T_>(val) ) ;
return *this ;
}
@@ -851,7 +818,7 @@ class optional
// Assigns from a T (deep-moves the rhs value)
optional& operator= ( rval_reference_type val )
{
this->assign( optional_detail::move(val) ) ;
this->assign( optional_detail::move_(val) ) ;
return *this ;
}
@@ -871,17 +838,17 @@ class optional
template<class... Args>
void emplace ( Args&&... args )
{
this->emplace_assign( optional_detail::forward<Args>(args)... );
this->emplace_assign( optional_detail::forward_<Args>(args)... );
}
template<class... Args>
explicit optional ( in_place_init_t, Args&&... args )
: base( in_place_init, optional_detail::forward<Args>(args)... )
: base( in_place_init, optional_detail::forward_<Args>(args)... )
{}
template<class... Args>
explicit optional ( in_place_init_if_t, bool cond, Args&&... args )
: base( in_place_init_if, cond, optional_detail::forward<Args>(args)... )
: base( in_place_init_if, cond, optional_detail::forward_<Args>(args)... )
{}
void swap( optional & arg )
@@ -915,7 +882,7 @@ class optional
reference_type operator *() BOOST_OPTIONAL_REF_QUAL { return this->get() ; }
#ifndef BOOST_NO_CXX11_REF_QUALIFIERS
reference_type_of_temporary_wrapper operator *() && { return optional_detail::move(this->get()) ; }
reference_type_of_temporary_wrapper operator *() && { return optional_detail::move_(this->get()) ; }
#endif
reference_const_type value() BOOST_OPTIONAL_CONST_REF_QUAL
@@ -940,7 +907,7 @@ class optional
if (this->is_initialized())
return get();
else
return optional_detail::forward<U>(v);
return optional_detail::forward_<U>(v);
}
template <typename F>
@@ -956,7 +923,7 @@ class optional
reference_type_of_temporary_wrapper value() &&
{
if (this->is_initialized())
return optional_detail::move(this->get()) ;
return optional_detail::move_(this->get()) ;
else
throw_exception(bad_optional_access());
}
@@ -965,16 +932,16 @@ class optional
value_type value_or ( U&& v ) &&
{
if (this->is_initialized())
return optional_detail::move(get());
return optional_detail::move_(get());
else
return optional_detail::forward<U>(v);
return optional_detail::forward_<U>(v);
}
template <typename F>
value_type value_or_eval ( F f ) &&
{
if (this->is_initialized())
return optional_detail::move(get());
return optional_detail::move_(get());
else
return f();
}
@@ -1005,7 +972,7 @@ class optional
optional<typename optional_detail::result_of<F, reference_type_of_temporary_wrapper>::type> map(F f) &&
{
if (this->has_value())
return f(optional_detail::move(this->get()));
return f(optional_detail::move_(this->get()));
else
return none;
}
@@ -1037,7 +1004,7 @@ class optional
flat_map(F f) &&
{
if (this->has_value())
return f(optional_detail::move(get()));
return f(optional_detail::move_(get()));
else
return none;
}
@@ -1048,128 +1015,34 @@ class optional
explicit operator bool() const BOOST_NOEXCEPT { return this->has_value() ; }
} ;
template<class T>
class optional<T&&>
{
static_assert(sizeof(T) == 0, "Optional rvalue references are illegal.");
} ;
} // namespace boost
#include <boost/optional/detail/optional_swap.hpp>
#endif // pre-C++14 impl
namespace boost {
template <class T>
class optional<T&&>
{
static_assert(sizeof(T) == 0, "Optional rvalue references are illegal.");
};
}
#ifndef BOOST_OPTIONAL_CONFIG_DONT_SPECIALIZE_OPTIONAL_REFS
# include <boost/optional/detail/optional_reference_spec.hpp>
#endif
namespace boost {
template<class T>
inline
optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type> make_optional ( T && v )
{
return optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>(optional_detail::forward<T>(v));
}
// Returns optional<T>(cond,v)
template<class T>
inline
optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type> make_optional ( bool cond, T && v )
{
return optional<BOOST_DEDUCED_TYPENAME boost::decay<T>::type>(cond,optional_detail::forward<T>(v));
}
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
// No-throw
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
get ( optional<T> const& opt )
{
return opt.get() ;
}
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
get ( optional<T>& opt )
{
return opt.get() ;
}
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
// No-throw
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
get ( optional<T> const* opt )
{
return opt->get_ptr() ;
}
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
get ( optional<T>* opt )
{
return opt->get_ptr() ;
}
// Returns a reference to the value if this is initialized, otherwise, the behaviour is UNDEFINED.
// No-throw
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type
get_optional_value_or ( optional<T> const& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_const_type v )
{
return opt.get_value_or(v) ;
}
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::reference_type
get_optional_value_or ( optional<T>& opt, BOOST_DEDUCED_TYPENAME optional<T>::reference_type v )
{
return opt.get_value_or(v) ;
}
// Returns a pointer to the value if this is initialized, otherwise, returns NULL.
// No-throw
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::pointer_const_type
get_pointer ( optional<T> const& opt )
{
return opt.get_ptr() ;
}
template<class T>
inline
BOOST_DEDUCED_TYPENAME optional<T>::pointer_type
get_pointer ( optional<T>& opt )
{
return opt.get_ptr() ;
}
} // namespace boost
#ifndef BOOST_NO_IOSTREAM
namespace boost {
// The following declaration prevents a bug where operator safe-bool is used upon streaming optional object if you forget the IO header.
template<class CharType, class CharTrait>
std::basic_ostream<CharType, CharTrait>&
operator<<(std::basic_ostream<CharType, CharTrait>& os, optional_detail::optional_tag const&)
{
static_assert(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>");
return os;
}
} // namespace boost
#endif // BOOST_NO_IOSTREAM
#include <boost/optional/detail/optional_hash.hpp>
#include <boost/optional/detail/optional_relops.hpp>
#include <boost/optional/detail/optional_swap.hpp>
#include <boost/optional/detail/optional_nonmember_interface.hpp>
#endif // header guard
+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
{
+4 -1
View File
@@ -28,7 +28,6 @@ project
cxx11_explicit_conversion_operators
# cxx11_noexcept
cxx11_rvalue_references
cxx11_static_assert
cxx11_variadic_templates
]
;
@@ -37,7 +36,9 @@ project
run optional_test.cpp : : : <library>/boost/bind//boost_bind ;
run optional_test_assign.cpp ;
run optional_test_swap.cpp ;
compile optional_test_constexpr.cpp ;
compile optional_test_wuninitialized.cpp ;
compile optional_test_fwd_header.cpp ;
run optional_test_conversions_from_U.cpp ;
run optional_test_convert_from_T.cpp ;
run optional_test_convert_assign.cpp ;
@@ -47,6 +48,7 @@ run optional_test_flat_map.cpp ;
run optional_test_hash.cpp ;
run optional_test_map.cpp ;
run optional_test_tie.cpp : : : <library>/boost/tuple//boost_tuple ;
run optional_test_ranges_find.cpp ;
run optional_test_ref_assign_portable_minimum.cpp ;
run optional_test_ref_assign_mutable_int.cpp ;
run optional_test_ref_assign_const_int.cpp ;
@@ -78,6 +80,7 @@ compile-fail optional_test_fail3b.cpp ;
compile-fail optional_test_ref_fail1.cpp ;
compile-fail optional_test_ref_fail3.cpp ;
compile-fail optional_test_ref_fail4.cpp ;
compile-fail optional_test_ref_fail_convert_from_temporary_optional_T.cpp ;
compile-fail optional_test_inplace_fail.cpp ;
compile-fail optional_test_inplace_fail2.cpp ;
compile-fail optional_test_fail_implicit_bool_convert.cpp ;
+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>());
}
+132
View File
@@ -0,0 +1,132 @@
// Copyright (C) 2026, Andrzej Krzemieński.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
#include "boost/optional.hpp"
#ifdef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
struct Record
{
int i;
constexpr explicit Record(int i) : i(i) {}
constexpr int operator()() const { return i; }
};
struct Guard
{
int i;
constexpr explicit Guard(int i) : i(i) {}
Guard(Guard&&) = delete;
};
static_assert(boost::none == boost::none, "");
static_assert(!(boost::none != boost::none), "");
namespace test_int
{
constexpr boost::optional<int> oN;
static_assert(!oN, "");
static_assert(oN == boost::none, "");
static_assert(oN <= boost::none, "");
static_assert(!(oN != boost::none), "");
static_assert(oN == oN, "");
static_assert(!oN.has_value(), "");
static_assert(oN.value_or({}) == 0, "");
static_assert(oN.value_or(0) == 0, "");
static_assert(oN.value_or_eval(Record(9)) == 9, "");
constexpr boost::optional<int> o1 (1);
constexpr boost::optional<int> o2 {2};
static_assert(o1, "");
static_assert(o1.has_value(), "");
static_assert(o1 != boost::none, "");
static_assert(o1 != oN, "");
static_assert(o1 > oN, "");
static_assert(o1 >= oN, "");
static_assert(*o1 == 1, "");
static_assert(o1.value() == 1, "");
static_assert(o1.value_or(0) == 1, "");
static_assert(o1.value_or({}) == 1, "");
static_assert(o1.value_or_eval(Record(9)) == 1, "");
static_assert(o1 == 1, "");
static_assert(o2, "");
static_assert(o2 != o1, "");
static_assert(o2 > o1, "");
#ifdef BOOST_OPTIONAL_CONSTEXPR_COPY
constexpr boost::optional<int> oNc = oN;
constexpr boost::optional<int> oNd = boost::none;
constexpr boost::optional<int> oNe = {};
static_assert(oNc == oN, "");
static_assert(oNd == oN, "");
static_assert(oNe == oN, "");
constexpr bool test_reset() {
boost::optional<int> o = 1;
assert(o);
o = boost::none;
assert(!o);
return o == boost::none;
}
static_assert(test_reset(), "");
#endif
}
namespace test_record
{
constexpr boost::optional<Record> rN (boost::none);
constexpr boost::optional<Record> r1 (Record(1));
constexpr boost::optional<Record> r2 (boost::in_place_init, 2);
static_assert(!rN, "");
static_assert(rN == boost::none, "");
static_assert(r1, "");
static_assert(r1 != boost::none, "");
static_assert(r2, "");
static_assert(rN.value_or(Record(9)).i == 9, "");
static_assert(r1->i == 1, "");
static_assert(r2.value().i == 2, "");
}
namespace test_guard
{
constexpr boost::optional<Guard> g1 {boost::in_place_init, 1};
constexpr boost::optional<Guard> gNa {boost::none};
constexpr boost::optional<Guard> gNb;
static_assert(g1, "");
static_assert(!!g1, "");
static_assert(g1 != boost::none, "");
static_assert(!(g1 == boost::none), "");
static_assert(g1.has_value(), "");
static_assert(!gNa, "");
static_assert(!gNa.has_value(), "");
static_assert(gNa == boost::none, "");
static_assert(!(gNa != boost::none), "");
static_assert(!gNb, "");
static_assert(!gNb.has_value(), "");
static_assert(gNb == boost::none, "");
static_assert(!(gNb != boost::none), "");
}
namespace test_optional_ref
{
constexpr int gi = 9;
constexpr boost::optional<const int&> iref = gi;
static_assert(iref, "");
static_assert(*iref == 9, "");
}
#endif // BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
@@ -55,5 +55,6 @@ int main()
{
// Invokes boost::optional copy constructor. Should not invoke wrapper constructor from U.
boost::optional< wrapper< int > > res = foo();
(void)res;
return 0;
}
+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
+2
View File
@@ -45,6 +45,8 @@ void test_optional_of_superconverting_T() // compile-time test
superconv<optional<int> > s;
superconv<optional<int> > & rs = s;
optional<superconv<optional<int> > > os = rs;
(void)s;
(void)os;
#endif
}
@@ -29,4 +29,3 @@ void test_implicit_conversion_to_bool()
boost::optional<T> opt;
opt.value_or(U());
}
+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);
}
+33
View File
@@ -105,9 +105,42 @@ void test_assign()
#endif
}
// begin Boost.Log case
template <typename CharT>
struct basic_formatter
{
template< typename FunT >
basic_formatter(FunT&&) {}
template< typename FunT >
basic_formatter& operator= (FunT&&)
{
return *this;
}
};
template< typename CharT>
struct chained_formatter
{
};
void test_boost_log_case()
{
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
boost::optional<basic_formatter<char>> of( boost::in_place(chained_formatter<char>()) );
of = boost::in_place(chained_formatter<char>());
#endif //BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
}
// end Boost.Log case
int main()
{
test_ctor();
test_assign();
test_boost_log_case();
return boost::report_errors();
}
+36 -36
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);
@@ -32,6 +32,7 @@ void test()
//BOOST_TEST(v);
boost::optional<boost::optional<int>> vv;
bool xx = vv?true : false;
(void)xx;
BOOST_TEST_EQ(*v, 7);
#endif
}
+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
+70
View File
@@ -0,0 +1,70 @@
// Copyright (C) 2026 Andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// akrzemi1@gmail.com
#include "boost/optional/optional.hpp"
#include "boost/core/lightweight_test.hpp"
#include <type_traits>
#ifndef BOOST_NO_CXX20_HDR_RANGES
#include <ranges>
#include <concepts>
#include <iterator>
#include <array>
#include <string>
static_assert(std::equality_comparable<boost::none_t>, "boost::none shall be equality comparable");
template <typename T>
void test_that_you_can_find_none_in_a_range_of_optional(T x, T y)
{
static_assert(std::equality_comparable_with<boost::optional<T>, boost::none_t>, "boost::none shall satisfy the concept");
static_assert(std::equality_comparable_with<boost::none_t, boost::optional<T> >, "boost::none shall satisfy the concept");
static_assert(std::indirect_binary_predicate<std::ranges::equal_to, const boost::optional<T>*, const boost::none_t*>, "boost::none shall satisfy the concept");
// [0] [1] [2]
std::array<boost::optional<T>, 3> arr = {{ x, boost::none, y }};
auto it = std::ranges::find(arr, boost::none);
BOOST_TEST_EQ(std::distance(arr.begin(), it), 1);
}
#endif // BOOST_NO_CXX20_HDR_RANGES
# if (defined __GNUC__) && (!defined BOOST_INTEL_CXX_VERSION) && (!defined __clang__)
# if (__GNUC__ <= 4)
# define BOOST_OPTIONAL_TEST_INSUFFICIENT_TYPE_TRAIT_SUPPORT
# endif
# endif
#ifndef BOOST_OPTIONAL_TEST_INSUFFICIENT_TYPE_TRAIT_SUPPORT
static_assert(std::is_trivially_copyable<boost::none_t>::value, "boost::none shall be trivially copyable");
#endif
void test_that_none_is_equal_to_none()
{
BOOST_TEST(boost::none == boost::none);
BOOST_TEST(!(boost::none != boost::none));
auto None = boost::none;
BOOST_TEST(None == boost::none);
BOOST_TEST(!(None != boost::none));
}
int main()
{
#ifndef BOOST_NO_CXX20_HDR_RANGES
test_that_you_can_find_none_in_a_range_of_optional(1, 2);
test_that_you_can_find_none_in_a_range_of_optional<std::string>("one", "two");
#endif
test_that_none_is_equal_to_none();
return boost::report_errors();
}
@@ -0,0 +1,21 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com
//
#include "boost/optional.hpp"
//
// THIS TEST SHOULD FAIL TO COMPILE
//
void optional_reference__test_no_converting_initialization()
{
boost::optional<const int&> o (boost::optional<int>(1));
(void)o;
}
+121 -14
View File
@@ -24,7 +24,13 @@ using boost::none;
struct Value
{
int val;
explicit Value(int v) : val(v) {}
BOOST_CONSTEXPR explicit Value(int v) : val(v) {}
};
struct Guard
{
int val;
BOOST_CONSTEXPR explicit Guard(int v) : val(v) {}
};
int val(int const& i)
@@ -37,6 +43,11 @@ int val(Value const& v)
return v.val;
}
int val(Guard const& v)
{
return v.val;
}
template <typename Tref>
optional<Tref&> make_opt_ref(Tref& v)
{
@@ -47,21 +58,21 @@ template <typename Tval, typename Tref>
void test_construct_from_optional_ref()
{
Tref v1 (1), v2 (2);
optional<Tref&> opt_ref0;
optional<Tref&> opt_ref1 (v1);
optional<Tval> opt_val0 (opt_ref0);
optional<Tval> opt_val1 (opt_ref1);
optional<Tval> opt_val2 (make_opt_ref(v2));
BOOST_TEST (!opt_val0);
BOOST_TEST (opt_val1);
BOOST_TEST (opt_val2);
BOOST_TEST_EQ (1, val(*opt_val1));
BOOST_TEST_EQ (2, val(*opt_val2));
BOOST_TEST (boost::addressof(*opt_val1) != boost::addressof(v1));
BOOST_TEST (boost::addressof(*opt_val2) != boost::addressof(v2));
}
@@ -70,29 +81,121 @@ template <typename Tval, typename Tref>
void test_assign_from_optional_ref()
{
Tref v1 (1), v2 (2);
optional<Tref&> opt_ref0;
optional<Tref&> opt_ref1 (v1);
optional<Tval> opt_val0;
optional<Tval> opt_val1;
optional<Tval> opt_val2;
opt_val0 = opt_ref0;
opt_val1 = opt_ref1;
opt_val2 = make_opt_ref(v2);
BOOST_TEST (!opt_val0);
BOOST_TEST (opt_val1);
BOOST_TEST (opt_val2);
BOOST_TEST_EQ (1, val(*opt_val1));
BOOST_TEST_EQ (2, val(*opt_val2));
BOOST_TEST (boost::addressof(*opt_val1) != boost::addressof(v1));
BOOST_TEST (boost::addressof(*opt_val2) != boost::addressof(v2));
}
template <typename T>
void test_convert_optional_T_to_optional_T_ref()
{
#ifdef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
using boost::optional;
using boost::in_place_init;
{ // optional<T>& -> optional<T&>
optional<T> ovN, ov1(in_place_init, 1), ov2(in_place_init, 2);
optional<T&> orN = ovN;
optional<T&> or1 = ov1;
optional<T&> or2 = ov2;
BOOST_TEST_EQ (!!orN, !!ovN);
BOOST_TEST_EQ (!!or1, !!ov1);
BOOST_TEST_EQ (!!or2, !!ov2);
BOOST_TEST (or1);
BOOST_TEST (or2);
BOOST_TEST_EQ (val(*or1), 1);
BOOST_TEST_EQ (val(*or2), 2);
BOOST_TEST (boost::addressof(*or1) == boost::addressof(*ov1));
BOOST_TEST (boost::addressof(*or2) == boost::addressof(*ov2));
}
{ // const optional<T>& -> optional<const T&>
constexpr optional<T> ovN;
constexpr optional<T> ov1(in_place_init, 1);
constexpr optional<T> ov2(in_place_init, 2);
optional<const T&> orN = ovN;
optional<const T&> or1 = ov1;
optional<const T&> or2 = ov2;
BOOST_TEST_EQ (!!orN, !!ovN);
BOOST_TEST_EQ (!!or1, !!ov1);
BOOST_TEST_EQ (!!or2, !!ov2);
BOOST_TEST (or1);
BOOST_TEST (or2);
BOOST_TEST_EQ (val(*or1), 1);
BOOST_TEST_EQ (val(*or2), 2);
BOOST_TEST (boost::addressof(*or1) == boost::addressof(*ov1));
BOOST_TEST (boost::addressof(*or2) == boost::addressof(*ov2));
}
{ // optional<const T>& -> optional<const T&>
optional<const T> ovN;
optional<const T> ov1(in_place_init, 1);
optional<const T> ov2(in_place_init, 2);
optional<const T&> orN = ovN;
optional<const T&> or1 = ov1;
optional<const T&> or2 = ov2;
BOOST_TEST_EQ (!!orN, !!ovN);
BOOST_TEST_EQ (!!or1, !!ov1);
BOOST_TEST_EQ (!!or2, !!ov2);
BOOST_TEST (or1);
BOOST_TEST (or2);
BOOST_TEST_EQ (val(*or1), 1);
BOOST_TEST_EQ (val(*or2), 2);
BOOST_TEST (boost::addressof(*or1) == boost::addressof(*ov1));
BOOST_TEST (boost::addressof(*or2) == boost::addressof(*ov2));
}
{ // optional<T>& -> optional<const T&>
optional<T> ovN;
optional<T> ov1(in_place_init, 1);
optional<T> ov2(in_place_init, 2);
optional<const T&> orN = ovN;
optional<const T&> or1 = ov1;
optional<const T&> or2 = ov2;
BOOST_TEST_EQ (!!orN, !!ovN);
BOOST_TEST_EQ (!!or1, !!ov1);
BOOST_TEST_EQ (!!or2, !!ov2);
BOOST_TEST (or1);
BOOST_TEST (or2);
BOOST_TEST_EQ (val(*or1), 1);
BOOST_TEST_EQ (val(*or2), 2);
BOOST_TEST (boost::addressof(*or1) == boost::addressof(*ov1));
BOOST_TEST (boost::addressof(*or2) == boost::addressof(*ov2));
}
#endif // BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
}
int main()
{
@@ -100,17 +203,21 @@ int main()
test_construct_from_optional_ref<int, int const>();
test_construct_from_optional_ref<int const, int const>();
test_construct_from_optional_ref<int const, int>();
test_construct_from_optional_ref<Value, Value>();
test_construct_from_optional_ref<Value, Value const>();
test_construct_from_optional_ref<Value const, Value const>();
test_construct_from_optional_ref<Value const, Value>();
test_assign_from_optional_ref<int, int>();
test_assign_from_optional_ref<int, int const>();
test_assign_from_optional_ref<Value, Value>();
test_assign_from_optional_ref<Value, Value const>();
test_convert_optional_T_to_optional_T_ref<int>();
test_convert_optional_T_to_optional_T_ref<Value>();
test_convert_optional_T_to_optional_T_ref<Guard>();
return boost::report_errors();
}
+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()