Compare commits

..

11 Commits

Author SHA1 Message Date
Andrzej Krzemienski 0fca17a0a8 GHA fix 3 2026-02-16 13:00:57 +01:00
Andrzej Krzemienski 3ce5e44ae2 GHA fix 2 2026-02-16 12:39:36 +01:00
Andrzej Krzemienski 64aa3f918c change GHA setup 2026-02-16 12:27:50 +01:00
Andrzej Krzemienski 003b1e5415 fix ranges triviality test on too old GCC 2026-02-10 19:12:41 +01:00
Andrzej Krzemienski d3f6501728 docs: operator bool fix 2026-02-10 01:54:32 +01:00
Andrzej Krzemienski 802715d295 add comparison for none and docs 2026-02-10 01:51:53 +01:00
Andrzej Krzemienski 437c1eb626 really fix the factory bug 2026-02-08 23:42:24 +01:00
Andrzej Krzemienski 6a2e169f23 fix conditional constexpr init in MSVC 2026-02-08 20:01:24 +01:00
Andrzej Krzemienski f0059887bc fix factory application syntax 2026-02-08 18:56:56 +01:00
Andrzej Krzemienski b8e5c07f2f fix constexpr tests 2026-02-08 12:15:52 +01:00
Andrzej Krzemienski f564e11dea add robust constexpr support 2026-02-08 11:27:30 +01:00
15 changed files with 57 additions and 319 deletions
+6 -1
View File
@@ -142,8 +142,9 @@ jobs:
- toolset: clang - toolset: clang
compiler: clang++-16 compiler: clang++-16
cxxstd: "03,11,14,17,20,2b" cxxstd: "03,11,14,17,20,2b"
os: ubuntu-24.04 os: ubuntu-latest
install: clang-16 install: clang-16
container: ubuntu:24.04
- toolset: clang - toolset: clang
compiler: clang++-17 compiler: clang++-17
cxxstd: "03,11,14,17,20,2b" cxxstd: "03,11,14,17,20,2b"
@@ -224,6 +225,10 @@ jobs:
cxxstd: 14,latest cxxstd: 14,latest
addrmd: 32,64 addrmd: 32,64
os: windows-2019 os: windows-2019
- toolset: msvc-14.1
cxxstd: "11,14,17,20,latest"
addrmd: 32,64
os: windows-2019
- toolset: msvc-14.2 - toolset: msvc-14.2
cxxstd: "14,17,20,latest" cxxstd: "14,17,20,latest"
addrmd: 32,64 addrmd: 32,64
-12
View File
@@ -50,18 +50,6 @@ In the general case, the internal representation is something equivalent to:
alignas(T) char _value [sizeof(T)]; 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, 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`, 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 which indicates whether we have the value or not, and, if we do have value, and
-3
View File
@@ -197,9 +197,6 @@ They are empty, trivially copyable classes with disabled default constructor.
template<class F> constexpr auto flat_map( F f ) & -> ``['see below]``; ``[link reference_optional_flat_map __GO_TO__]`` template<class F> constexpr auto flat_map( F f ) & -> ``['see below]``; ``[link reference_optional_flat_map __GO_TO__]``
template<class F> constexpr auto flat_map( F f ) && -> ``['see below]``; ``[link reference_optional_flat_map_move __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 const* get_ptr() const ; ``[link reference_optional_get_ptr __GO_TO__]``
T* get_ptr() ; ``[link reference_optional_get_ptr __GO_TO__]`` T* get_ptr() ; ``[link reference_optional_get_ptr __GO_TO__]``
+9 -30
View File
@@ -2,7 +2,6 @@
Boost.Optional Boost.Optional
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
Copyright (C) 2014 - 2026 Andrzej Krzemieński.
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at (See accompanying file LICENSE_1_0.txt or copy at
@@ -26,31 +25,31 @@ __SPACE__
[: `constexpr optional<T>::optional() noexcept;`] [: `constexpr optional<T>::optional() noexcept;`]
* [*Postconditions:] `*this` does ['not] contain a value (is "uninitialized"). * [*Effect:] Default-Constructs an `optional`.
* [*Remarks:] No contained value is initialized. For every object type `T` these constructors are core constant expressions. * [*Postconditions:] `*this` is [_uninitialized].
* [*Notes:] T's default constructor [_is not] called.
* [*Example:] * [*Example:]
`` ``
optional<T> oN ; optional<T> def ;
assert ( !oN ) ; assert ( !def ) ;
`` ``
__SPACE__ __SPACE__
[#reference_optional_constructor_none_t] [#reference_optional_constructor_none_t]
[: `constexpr optional<T>::optional( none_t ) noexcept;`] [: `constexpr optional<T>::optional( none_t ) noexcept;`]
* [*Postconditions:] `*this` does ['not] contain a value (is "uninitialized"). * [*Effect:] Constructs an `optional` uninitialized.
* [*Remarks:] No contained value is initialized. For every object type `T` these constructors are core constant expressions. The expression * [*Postconditions:] `*this` is [_uninitialized].
* [*Notes:] `T`'s default constructor [_is not] called. The expression
`boost::none` denotes an instance of `boost::none_t` that can be used as `boost::none` denotes an instance of `boost::none_t` that can be used as
the parameter. the parameter.
* [*Example:] * [*Example:]
`` ``
#include <boost/none.hpp> #include <boost/none.hpp>
optional<T> n(none) ; optional<T> n(none) ;
assert ( !n ) ; assert ( !n ) ;
assert ( n == none ) ;
`` ``
__SPACE__ __SPACE__
@@ -753,26 +752,6 @@ __SPACE__
__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] [#reference_optional_get_value_or_value]
[: `T const& optional<T>::get_value_or( T const& default) const ;`] [: `T const& optional<T>::get_value_or( T const& default) const ;`]
+1
View File
@@ -72,6 +72,7 @@ The implementation uses the following other Boost modules:
# assert # assert
# config # config
# core # core
# static_assert
# throw_exception # throw_exception
# type_traits # type_traits
+1 -11
View File
@@ -47,17 +47,7 @@
`std::ranges::find(rng, boost::none)`] [`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`. ] ] `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] [endsect][/ std_comp]
+2 -23
View File
@@ -18,7 +18,7 @@
`constexpr` support: `constexpr` support:
* In C++11, some constructors and `const`-qualified accessors become usable * In C++11, some constructors and `const`-qualified accessors become usable
in compile-time contexts (are ['core constant expressions]) for types in compile-time contexts (are ['core constant expressions] for types
satisfying certain constraints. satisfying certain constraints.
* In C++14 even some mutating operations become core constant expressions (those * 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 that do not require changing the state of `optional` from not having a value to
@@ -26,7 +26,7 @@
* In C++17 all constructors (including copy and move) become core constant expressions * In C++17 all constructors (including copy and move) become core constant expressions
for co-operating types. for co-operating types.
This addresses issues [@https://github.com/boostorg/optional/issues/132 #132] and [@https://github.com/boostorg/optional/issues/143 #143]. This addresses [@https://github.com/boostorg/optional/issues/143 issue #143].
* *Breaking change.* In the said implementation, abandoned the mechanism for customizing * *Breaking change.* In the said implementation, abandoned the mechanism for customizing
`swap`. Hardly anyone knows about this mechanism and it was never documented. `swap`. Hardly anyone knows about this mechanism and it was never documented.
@@ -37,31 +37,10 @@
* Construct `o = u`, where `o` is of type `optional<T>` and `u` is of type `U` convertible to `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`. 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>` * `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), 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. 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] [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. * *Breaking change.* Dropped support for C++03. C++11 is now the required minimum; at least some C++11 features.
@@ -74,20 +74,9 @@ union constexpr_union_storage_t
constexpr constexpr_union_storage_t( trivial_init_t ) noexcept : dummy_() {}; 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> template <class... Args>
constexpr constexpr_union_storage_t( Args&&... args ) : value_(forward_<Args>(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 //~constexpr_union_storage_t() = default; // No need to destroy a trivially-destructible type
}; };
@@ -99,20 +88,9 @@ union fallback_union_storage_t
constexpr fallback_union_storage_t( trivial_init_t ) noexcept : dummy_() {}; 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> template <class... Args>
constexpr fallback_union_storage_t( Args&&... args ) : value_(forward_<Args>(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. ~fallback_union_storage_t(){} // My owner will destroy the `T` if needed.
// Cannot default in a union with nontrivial `T`. // Cannot default in a union with nontrivial `T`.
}; };
@@ -144,15 +122,6 @@ struct constexpr_guarded_storage
BOOST_CXX14_CONSTEXPR void reset () noexcept { init_ = false; } BOOST_CXX14_CONSTEXPR void reset () noexcept { init_ = false; }
//~constexpr_guarded_storage() = default; //~constexpr_guarded_storage() = default;
#if (defined(_MSC_VER) && 1910 <= _MSC_VER && _MSC_VER <= 1916)
// Workaround for MSVC 14.1x bug where it eagerly tries to define the copy/move operations
// these are declared but never defined
constexpr_guarded_storage(const constexpr_guarded_storage&);
constexpr_guarded_storage(constexpr_guarded_storage&&);
constexpr_guarded_storage& operator=(const constexpr_guarded_storage&);
constexpr_guarded_storage& operator=(constexpr_guarded_storage&&);
#endif
}; };
@@ -186,15 +155,6 @@ struct fallback_guarded_storage
} }
~fallback_guarded_storage() { if (init_) storage_.value_.T::~T(); } ~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
}; };
@@ -389,9 +349,7 @@ namespace boost {
} }
template <typename U, template <typename U,
BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U&&>), BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U&&>)>
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_typed_in_place_factory<U>),
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_in_place_factory<U>)>
constexpr explicit optional(U&& v) constexpr explicit optional(U&& v)
: storage(optional_ns::in_place_init, optional_detail::forward_<U>(v)) : storage(optional_ns::in_place_init, optional_detail::forward_<U>(v))
{} {}
@@ -401,20 +359,6 @@ namespace boost {
: storage(in_place_init, optional_detail::forward_<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 BOOST_CXX14_CONSTEXPR void reset() noexcept
{ {
storage.reset(); storage.reset();
@@ -519,9 +463,7 @@ namespace boost {
BOOST_OPTIONAL_REQUIRES(!::std::is_same<typename ::std::decay<U>::type, optional>), 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(!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_constructible<T, U>),
BOOST_OPTIONAL_REQUIRES(::std::is_assignable<T&, U>), BOOST_OPTIONAL_REQUIRES(::std::is_assignable<T&, U>)
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_typed_in_place_factory<U>),
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_in_place_factory<U>)
> >
BOOST_OPTIONAL_CXX20_CONSTEXPR optional& operator=(U&& v) BOOST_OPTIONAL_CXX20_CONSTEXPR optional& operator=(U&& v)
{ {
+1 -1
View File
@@ -28,6 +28,7 @@ project
cxx11_explicit_conversion_operators cxx11_explicit_conversion_operators
# cxx11_noexcept # cxx11_noexcept
cxx11_rvalue_references cxx11_rvalue_references
cxx11_static_assert
cxx11_variadic_templates cxx11_variadic_templates
] ]
; ;
@@ -80,7 +81,6 @@ compile-fail optional_test_fail3b.cpp ;
compile-fail optional_test_ref_fail1.cpp ; compile-fail optional_test_ref_fail1.cpp ;
compile-fail optional_test_ref_fail3.cpp ; compile-fail optional_test_ref_fail3.cpp ;
compile-fail optional_test_ref_fail4.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_fail.cpp ;
compile-fail optional_test_inplace_fail2.cpp ; compile-fail optional_test_inplace_fail2.cpp ;
compile-fail optional_test_fail_implicit_bool_convert.cpp ; compile-fail optional_test_fail_implicit_bool_convert.cpp ;
+21
View File
@@ -10,6 +10,7 @@
// akrzemi1@gmail.com // akrzemi1@gmail.com
#include "boost/optional.hpp" #include "boost/optional.hpp"
#include <string>
#ifdef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION #ifdef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
@@ -129,4 +130,24 @@ namespace test_optional_ref
static_assert(*iref == 9, ""); static_assert(*iref == 9, "");
} }
namespace test_msvc_14_1
{
struct Aggr
{
boost::optional<std::string> os;
};
void test()
{
Aggr a;
Aggr b = a;
b = a;
Aggr c = Aggr();
b = Aggr();
(void)a;
(void)b;
(void)c;
}
}
#endif // BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION #endif // BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
-2
View File
@@ -45,8 +45,6 @@ void test_optional_of_superconverting_T() // compile-time test
superconv<optional<int> > s; superconv<optional<int> > s;
superconv<optional<int> > & rs = s; superconv<optional<int> > & rs = s;
optional<superconv<optional<int> > > os = rs; optional<superconv<optional<int> > > os = rs;
(void)s;
(void)os;
#endif #endif
} }
-33
View File
@@ -105,42 +105,9 @@ void test_assign()
#endif #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() int main()
{ {
test_ctor(); test_ctor();
test_assign(); test_assign();
test_boost_log_case();
return boost::report_errors(); return boost::report_errors();
} }
@@ -32,7 +32,6 @@ void test()
//BOOST_TEST(v); //BOOST_TEST(v);
boost::optional<boost::optional<int>> vv; boost::optional<boost::optional<int>> vv;
bool xx = vv?true : false; bool xx = vv?true : false;
(void)xx;
BOOST_TEST_EQ(*v, 7); BOOST_TEST_EQ(*v, 7);
#endif #endif
} }
@@ -1,21 +0,0 @@
// 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;
}
+14 -121
View File
@@ -24,13 +24,7 @@ using boost::none;
struct Value struct Value
{ {
int val; int val;
BOOST_CONSTEXPR explicit Value(int v) : val(v) {} explicit Value(int v) : val(v) {}
};
struct Guard
{
int val;
BOOST_CONSTEXPR explicit Guard(int v) : val(v) {}
}; };
int val(int const& i) int val(int const& i)
@@ -43,11 +37,6 @@ int val(Value const& v)
return v.val; return v.val;
} }
int val(Guard const& v)
{
return v.val;
}
template <typename Tref> template <typename Tref>
optional<Tref&> make_opt_ref(Tref& v) optional<Tref&> make_opt_ref(Tref& v)
{ {
@@ -58,21 +47,21 @@ template <typename Tval, typename Tref>
void test_construct_from_optional_ref() void test_construct_from_optional_ref()
{ {
Tref v1 (1), v2 (2); Tref v1 (1), v2 (2);
optional<Tref&> opt_ref0; optional<Tref&> opt_ref0;
optional<Tref&> opt_ref1 (v1); optional<Tref&> opt_ref1 (v1);
optional<Tval> opt_val0 (opt_ref0); optional<Tval> opt_val0 (opt_ref0);
optional<Tval> opt_val1 (opt_ref1); optional<Tval> opt_val1 (opt_ref1);
optional<Tval> opt_val2 (make_opt_ref(v2)); optional<Tval> opt_val2 (make_opt_ref(v2));
BOOST_TEST (!opt_val0); BOOST_TEST (!opt_val0);
BOOST_TEST (opt_val1); BOOST_TEST (opt_val1);
BOOST_TEST (opt_val2); BOOST_TEST (opt_val2);
BOOST_TEST_EQ (1, val(*opt_val1)); BOOST_TEST_EQ (1, val(*opt_val1));
BOOST_TEST_EQ (2, val(*opt_val2)); BOOST_TEST_EQ (2, val(*opt_val2));
BOOST_TEST (boost::addressof(*opt_val1) != boost::addressof(v1)); BOOST_TEST (boost::addressof(*opt_val1) != boost::addressof(v1));
BOOST_TEST (boost::addressof(*opt_val2) != boost::addressof(v2)); BOOST_TEST (boost::addressof(*opt_val2) != boost::addressof(v2));
} }
@@ -81,121 +70,29 @@ template <typename Tval, typename Tref>
void test_assign_from_optional_ref() void test_assign_from_optional_ref()
{ {
Tref v1 (1), v2 (2); Tref v1 (1), v2 (2);
optional<Tref&> opt_ref0; optional<Tref&> opt_ref0;
optional<Tref&> opt_ref1 (v1); optional<Tref&> opt_ref1 (v1);
optional<Tval> opt_val0; optional<Tval> opt_val0;
optional<Tval> opt_val1; optional<Tval> opt_val1;
optional<Tval> opt_val2; optional<Tval> opt_val2;
opt_val0 = opt_ref0; opt_val0 = opt_ref0;
opt_val1 = opt_ref1; opt_val1 = opt_ref1;
opt_val2 = make_opt_ref(v2); opt_val2 = make_opt_ref(v2);
BOOST_TEST (!opt_val0); BOOST_TEST (!opt_val0);
BOOST_TEST (opt_val1); BOOST_TEST (opt_val1);
BOOST_TEST (opt_val2); BOOST_TEST (opt_val2);
BOOST_TEST_EQ (1, val(*opt_val1)); BOOST_TEST_EQ (1, val(*opt_val1));
BOOST_TEST_EQ (2, val(*opt_val2)); BOOST_TEST_EQ (2, val(*opt_val2));
BOOST_TEST (boost::addressof(*opt_val1) != boost::addressof(v1)); BOOST_TEST (boost::addressof(*opt_val1) != boost::addressof(v1));
BOOST_TEST (boost::addressof(*opt_val2) != boost::addressof(v2)); 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() int main()
{ {
@@ -203,21 +100,17 @@ int main()
test_construct_from_optional_ref<int, int const>(); 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 const>();
test_construct_from_optional_ref<int const, int>(); test_construct_from_optional_ref<int const, int>();
test_construct_from_optional_ref<Value, Value>(); test_construct_from_optional_ref<Value, Value>();
test_construct_from_optional_ref<Value, Value const>(); 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 const>();
test_construct_from_optional_ref<Value const, Value>(); test_construct_from_optional_ref<Value const, Value>();
test_assign_from_optional_ref<int, int>(); test_assign_from_optional_ref<int, int>();
test_assign_from_optional_ref<int, int const>(); test_assign_from_optional_ref<int, int const>();
test_assign_from_optional_ref<Value, Value>(); test_assign_from_optional_ref<Value, Value>();
test_assign_from_optional_ref<Value, Value const>(); 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(); return boost::report_errors();
} }