mirror of
https://github.com/boostorg/optional.git
synced 2026-06-11 20:01:10 +02:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1fb60cb53b | |||
| ecb241a919 | |||
| ff710d113c | |||
| 88e2378c8a | |||
| fa52755c88 | |||
| 76be15bfeb | |||
| 5d8e50a9aa | |||
| 37513ddbbf | |||
| 953b678b39 | |||
| b2057c8dfe | |||
| 1c13f5f724 | |||
| aa1cf1e76c | |||
| 938502da88 | |||
| 046357ce54 |
@@ -142,9 +142,8 @@ jobs:
|
||||
- toolset: clang
|
||||
compiler: clang++-16
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
os: ubuntu-latest
|
||||
os: ubuntu-24.04
|
||||
install: clang-16
|
||||
container: ubuntu:24.04
|
||||
- toolset: clang
|
||||
compiler: clang++-17
|
||||
cxxstd: "03,11,14,17,20,2b"
|
||||
@@ -225,10 +224,6 @@ jobs:
|
||||
cxxstd: 14,latest
|
||||
addrmd: 32,64
|
||||
os: windows-2019
|
||||
- toolset: msvc-14.1
|
||||
cxxstd: "11,14,17,20,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2019
|
||||
- toolset: msvc-14.2
|
||||
cxxstd: "14,17,20,latest"
|
||||
addrmd: 32,64
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -197,6 +197,9 @@ They are empty, trivially copyable classes with disabled default constructor.
|
||||
template<class F> constexpr auto flat_map( F f ) & -> ``['see below]``; ``[link reference_optional_flat_map __GO_TO__]``
|
||||
template<class F> constexpr auto flat_map( F f ) && -> ``['see below]``; ``[link reference_optional_flat_map_move __GO_TO__]``
|
||||
|
||||
constexpr operator optional<T&>() & noexcept; ``[link reference_optional_conversion_to_ref __GO_TO__]``
|
||||
constexpr operator optional<T const&>() const& noexcept; ``[link reference_optional_conversion_to_ref __GO_TO__]``
|
||||
|
||||
T const* get_ptr() const ; ``[link reference_optional_get_ptr __GO_TO__]``
|
||||
T* get_ptr() ; ``[link reference_optional_get_ptr __GO_TO__]``
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Boost.Optional
|
||||
|
||||
Copyright (c) 2003-2007 Fernando Luis Cacciola Carballal
|
||||
Copyright (C) 2014 - 2026 Andrzej Krzemieński.
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
(See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -25,31 +26,31 @@ __SPACE__
|
||||
|
||||
[: `constexpr optional<T>::optional() noexcept;`]
|
||||
|
||||
* [*Effect:] Default-Constructs an `optional`.
|
||||
* [*Postconditions:] `*this` is [_uninitialized].
|
||||
* [*Notes:] T's default constructor [_is not] called.
|
||||
* [*Postconditions:] `*this` does ['not] contain a value (is "uninitialized").
|
||||
* [*Remarks:] No contained value is initialized. For every object type `T` these constructors are core constant expressions.
|
||||
* [*Example:]
|
||||
``
|
||||
optional<T> def ;
|
||||
assert ( !def ) ;
|
||||
optional<T> oN ;
|
||||
assert ( !oN ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
[#reference_optional_constructor_none_t]
|
||||
|
||||
[#reference_optional_constructor_none_t]
|
||||
[: `constexpr optional<T>::optional( none_t ) noexcept;`]
|
||||
|
||||
* [*Effect:] Constructs an `optional` uninitialized.
|
||||
* [*Postconditions:] `*this` is [_uninitialized].
|
||||
* [*Notes:] `T`'s default constructor [_is not] called. The expression
|
||||
* [*Postconditions:] `*this` does ['not] contain a value (is "uninitialized").
|
||||
* [*Remarks:] No contained value is initialized. For every object type `T` these constructors are core constant expressions. The expression
|
||||
`boost::none` denotes an instance of `boost::none_t` that can be used as
|
||||
the parameter.
|
||||
* [*Example:]
|
||||
``
|
||||
#include <boost/none.hpp>
|
||||
|
||||
optional<T> n(none) ;
|
||||
assert ( !n ) ;
|
||||
assert ( n == none ) ;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
@@ -752,6 +753,26 @@ __SPACE__
|
||||
|
||||
__SPACE__
|
||||
|
||||
|
||||
[#reference_optional_conversion_to_ref]
|
||||
|
||||
[: `constexpr optional<T>::operator optional<T&>() & noexcept ;`]
|
||||
|
||||
* [*Returns:] If `*this` contains a value `optional<T&>(**this)`, otherwise `optional<T&>()`.
|
||||
|
||||
[: `constexpr optional<T>::operator optional<T const&>() const& noexcept ;`]
|
||||
|
||||
* [*Returns:] If `*this` contains a value `optional<T const&>(**this)`, otherwise `optional<T&>()`.
|
||||
|
||||
* [*Example:]
|
||||
``
|
||||
const optional<int> oi = 1;
|
||||
optional<const int&> ri = oi;
|
||||
``
|
||||
|
||||
__SPACE__
|
||||
|
||||
|
||||
[#reference_optional_get_value_or_value]
|
||||
|
||||
[: `T const& optional<T>::get_value_or( T const& default) const ;`]
|
||||
|
||||
@@ -72,7 +72,6 @@ The implementation uses the following other Boost modules:
|
||||
# assert
|
||||
# config
|
||||
# core
|
||||
# static_assert
|
||||
# throw_exception
|
||||
# type_traits
|
||||
|
||||
|
||||
@@ -47,7 +47,17 @@
|
||||
`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]
|
||||
|
||||
+27
-2
@@ -11,6 +11,10 @@
|
||||
|
||||
[section:relnotes Release Notes]
|
||||
|
||||
[heading Boost Release 1.xx]
|
||||
|
||||
* Fixed regression in the copy-initialization of `optional<bool>`. This fixes [@https://github.com/boostorg/optional/issues/146 issue #146].
|
||||
|
||||
[heading Boost Release 1.91]
|
||||
|
||||
* For compilers with full C++11 support (including "unrestricted unions" and ref-qualifiers)
|
||||
@@ -18,7 +22,7 @@
|
||||
`constexpr` support:
|
||||
|
||||
* 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.
|
||||
* 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
|
||||
@@ -26,7 +30,7 @@
|
||||
* In C++17 all constructors (including copy and move) become core constant expressions
|
||||
for co-operating types.
|
||||
|
||||
This addresses [@https://github.com/boostorg/optional/issues/143 issue #143].
|
||||
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.
|
||||
@@ -37,10 +41,31 @@
|
||||
* 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.
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
!defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) && \
|
||||
!defined(BOOST_NO_CXX11_UNRESTRICTED_UNION) && \
|
||||
!defined(BOOST_NO_CXX11_NOEXCEPT) && \
|
||||
!defined(BOOST_NO_CXX11_DEFAULTED_MOVES)
|
||||
!defined(BOOST_NO_CXX11_DEFAULTED_MOVES) && \
|
||||
!defined(BOOST_OPTIONAL_CONFIG_DISABLE_UNION_OPTIONAL)
|
||||
# define BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
#endif
|
||||
|
||||
|
||||
@@ -74,9 +74,20 @@ union constexpr_union_storage_t
|
||||
|
||||
constexpr constexpr_union_storage_t( trivial_init_t ) noexcept : dummy_() {};
|
||||
|
||||
#if defined(BOOST_GCC) && (__GNUC__ >= 7)
|
||||
// false positive, see https://github.com/boostorg/variant2/issues/55,
|
||||
// https://github.com/boostorg/url/issues/979
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
template <class... Args>
|
||||
constexpr constexpr_union_storage_t( Args&&... args ) : value_(forward_<Args>(args)...) {}
|
||||
|
||||
#if defined(BOOST_GCC) && (__GNUC__ >= 7)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
//~constexpr_union_storage_t() = default; // No need to destroy a trivially-destructible type
|
||||
};
|
||||
|
||||
@@ -88,9 +99,20 @@ union fallback_union_storage_t
|
||||
|
||||
constexpr fallback_union_storage_t( trivial_init_t ) noexcept : dummy_() {};
|
||||
|
||||
#if defined(BOOST_GCC) && (__GNUC__ >= 7)
|
||||
// false positive, see https://github.com/boostorg/variant2/issues/55,
|
||||
// https://github.com/boostorg/url/issues/979
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
template <class... Args>
|
||||
constexpr fallback_union_storage_t( Args&&... args ) : value_(forward_<Args>(args)...) {}
|
||||
|
||||
#if defined(BOOST_GCC) && (__GNUC__ >= 7)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
~fallback_union_storage_t(){} // My owner will destroy the `T` if needed.
|
||||
// Cannot default in a union with nontrivial `T`.
|
||||
};
|
||||
@@ -122,6 +144,15 @@ struct constexpr_guarded_storage
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
@@ -155,6 +186,15 @@ struct fallback_guarded_storage
|
||||
}
|
||||
|
||||
~fallback_guarded_storage() { if (init_) storage_.value_.T::~T(); }
|
||||
|
||||
#if (defined(_MSC_VER) && 1910 <= _MSC_VER && _MSC_VER <= 1916)
|
||||
// Workaround for MSVC 14.1x bug where it eagerly tries to define the copy/move operations
|
||||
// These are declared but never defined
|
||||
fallback_guarded_storage(const fallback_guarded_storage&);
|
||||
fallback_guarded_storage(fallback_guarded_storage&&);
|
||||
fallback_guarded_storage& operator=(const fallback_guarded_storage&);
|
||||
fallback_guarded_storage& operator=(fallback_guarded_storage&&);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -349,7 +389,11 @@ namespace boost {
|
||||
}
|
||||
|
||||
template <typename U,
|
||||
BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U&&>)>
|
||||
BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U&&>),
|
||||
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_typed_in_place_factory<U>),
|
||||
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_in_place_factory<U>),
|
||||
BOOST_OPTIONAL_REQUIRES(!BOOST_OPTIONAL_IS_TAGGED(optional_detail::optional_tag, U))
|
||||
>
|
||||
constexpr explicit optional(U&& v)
|
||||
: storage(optional_ns::in_place_init, optional_detail::forward_<U>(v))
|
||||
{}
|
||||
@@ -359,6 +403,20 @@ namespace boost {
|
||||
: 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();
|
||||
@@ -463,7 +521,9 @@ namespace boost {
|
||||
BOOST_OPTIONAL_REQUIRES(!::std::is_same<typename ::std::decay<U>::type, optional>),
|
||||
BOOST_OPTIONAL_REQUIRES(!optional_detail::conjunction<::std::is_scalar<T>, ::std::is_same<T, BOOST_OPTIONAL_DECAY(U)>>),
|
||||
BOOST_OPTIONAL_REQUIRES(::std::is_constructible<T, U>),
|
||||
BOOST_OPTIONAL_REQUIRES(::std::is_assignable<T&, U>)
|
||||
BOOST_OPTIONAL_REQUIRES(::std::is_assignable<T&, U>),
|
||||
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_typed_in_place_factory<U>),
|
||||
BOOST_OPTIONAL_REQUIRES(!optional_detail::is_in_place_factory<U>)
|
||||
>
|
||||
BOOST_OPTIONAL_CXX20_CONSTEXPR optional& operator=(U&& v)
|
||||
{
|
||||
|
||||
+2
-1
@@ -28,7 +28,6 @@ project
|
||||
cxx11_explicit_conversion_operators
|
||||
# cxx11_noexcept
|
||||
cxx11_rvalue_references
|
||||
cxx11_static_assert
|
||||
cxx11_variadic_templates
|
||||
]
|
||||
;
|
||||
@@ -41,6 +40,7 @@ compile optional_test_constexpr.cpp ;
|
||||
compile optional_test_wuninitialized.cpp ;
|
||||
compile optional_test_fwd_header.cpp ;
|
||||
run optional_test_conversions_from_U.cpp ;
|
||||
run optional_test_constructors.cpp ;
|
||||
run optional_test_convert_from_T.cpp ;
|
||||
run optional_test_convert_assign.cpp ;
|
||||
run optional_test_empty_braces.cpp ;
|
||||
@@ -81,6 +81,7 @@ compile-fail optional_test_fail3b.cpp ;
|
||||
compile-fail optional_test_ref_fail1.cpp ;
|
||||
compile-fail optional_test_ref_fail3.cpp ;
|
||||
compile-fail optional_test_ref_fail4.cpp ;
|
||||
compile-fail optional_test_ref_fail_convert_from_temporary_optional_T.cpp ;
|
||||
compile-fail optional_test_inplace_fail.cpp ;
|
||||
compile-fail optional_test_inplace_fail2.cpp ;
|
||||
compile-fail optional_test_fail_implicit_bool_convert.cpp ;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional.hpp"
|
||||
#include <string>
|
||||
|
||||
#ifdef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
|
||||
@@ -130,24 +129,4 @@ namespace test_optional_ref
|
||||
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
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
// Copyright (C) 2026 Andrzej Krzemienski.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// akrzemi1@gmail.com
|
||||
|
||||
#include "boost/optional/optional.hpp"
|
||||
#include "boost/core/lightweight_test.hpp"
|
||||
#include <string>
|
||||
|
||||
|
||||
using boost::optional;
|
||||
using boost::none;
|
||||
|
||||
struct MyBool
|
||||
{
|
||||
bool b;
|
||||
MyBool (bool b) : b(b) {}
|
||||
operator bool() const { return b; };
|
||||
};
|
||||
|
||||
struct MyExplicitBool
|
||||
{
|
||||
bool b;
|
||||
MyExplicitBool (bool b) : b(b) {}
|
||||
operator bool() const { return b; };
|
||||
};
|
||||
|
||||
struct Any
|
||||
{
|
||||
template <typename... T>
|
||||
Any(T&&...) {}
|
||||
};
|
||||
|
||||
struct JustCopyMoveCtor
|
||||
{
|
||||
JustCopyMoveCtor(JustCopyMoveCtor&&) = default;
|
||||
JustCopyMoveCtor(JustCopyMoveCtor const&) = default;
|
||||
JustCopyMoveCtor& operator=(JustCopyMoveCtor&&) = delete;
|
||||
JustCopyMoveCtor& operator=(JustCopyMoveCtor const&) = delete;
|
||||
JustCopyMoveCtor() = delete;
|
||||
};
|
||||
|
||||
struct JustDefault
|
||||
{
|
||||
JustDefault() = default;
|
||||
JustDefault(JustDefault&&) = delete;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
optional<T> empty_optional()
|
||||
{
|
||||
return optional<T>(); // this is to avoid "the most vexing parse"
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename U>
|
||||
void direct_test_ctor_optional_T_from_empty_optional_T()
|
||||
{
|
||||
optional<U> om;
|
||||
const optional<U> oc;
|
||||
BOOST_TEST(!om);
|
||||
BOOST_TEST(!oc);
|
||||
|
||||
{
|
||||
optional<T> ox = om;
|
||||
BOOST_TEST(!ox);
|
||||
|
||||
optional<T> oy = oc;
|
||||
BOOST_TEST(!oy);
|
||||
|
||||
optional<T> oz = empty_optional<U>();
|
||||
BOOST_TEST(!oz);
|
||||
}
|
||||
|
||||
{
|
||||
optional<T> ox = {om};
|
||||
BOOST_TEST(!ox);
|
||||
|
||||
optional<T> oy = {oc};
|
||||
BOOST_TEST(!oy);
|
||||
|
||||
optional<T> oz = {empty_optional<U>()};
|
||||
BOOST_TEST(!oz);
|
||||
}
|
||||
|
||||
{
|
||||
optional<T> ox{om};
|
||||
BOOST_TEST(!ox);
|
||||
|
||||
optional<T> oy{oc};
|
||||
BOOST_TEST(!oy);
|
||||
|
||||
optional<T> oz{empty_optional<U>()};
|
||||
BOOST_TEST(!oz);
|
||||
}
|
||||
|
||||
{
|
||||
optional<T> ox(om);
|
||||
BOOST_TEST(!ox);
|
||||
|
||||
optional<T> oy(oc);
|
||||
BOOST_TEST(!oy);
|
||||
|
||||
optional<T> oz(empty_optional<U>());
|
||||
BOOST_TEST(!oz);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void test_ctor_optional_T_from_empty_optional_T()
|
||||
{
|
||||
direct_test_ctor_optional_T_from_empty_optional_T<T, U>();
|
||||
direct_test_ctor_optional_T_from_empty_optional_T<const T, const U>();
|
||||
direct_test_ctor_optional_T_from_empty_optional_T<optional<T>, optional<U>>();
|
||||
direct_test_ctor_optional_T_from_empty_optional_T<optional<const T>, optional<const U>>();
|
||||
direct_test_ctor_optional_T_from_empty_optional_T<const optional<T>, const optional<U>>();
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void direct_test_ctor_optional_T_from_optional_U(U val)
|
||||
{
|
||||
optional<U> om;
|
||||
const optional<U> oc;
|
||||
BOOST_TEST(!om);
|
||||
BOOST_TEST(!oc);
|
||||
|
||||
{
|
||||
optional<T> ox{om};
|
||||
BOOST_TEST(!ox);
|
||||
|
||||
optional<T> oy{oc};
|
||||
BOOST_TEST(!oy);
|
||||
|
||||
optional<T> oz{empty_optional<U>()};
|
||||
BOOST_TEST(!oz);
|
||||
}
|
||||
|
||||
{
|
||||
optional<T> ox(om);
|
||||
BOOST_TEST(!ox);
|
||||
|
||||
optional<T> oy(oc);
|
||||
BOOST_TEST(!oy);
|
||||
|
||||
optional<T> oz(empty_optional<U>());
|
||||
BOOST_TEST(!oz);
|
||||
}
|
||||
|
||||
{
|
||||
optional<U> om {val};
|
||||
const optional<U> oc {val};
|
||||
|
||||
{
|
||||
optional<T> ox{om};
|
||||
BOOST_TEST(ox);
|
||||
|
||||
optional<T> oy{oc};
|
||||
BOOST_TEST(oy);
|
||||
|
||||
optional<T> oz{boost::make_optional(val)};
|
||||
BOOST_TEST(oz);
|
||||
}
|
||||
{
|
||||
optional<T> ox(om);
|
||||
BOOST_TEST(ox);
|
||||
|
||||
optional<T> oy(oc);
|
||||
BOOST_TEST(oy);
|
||||
|
||||
optional<T> oz(boost::make_optional(val));
|
||||
BOOST_TEST(oz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
void test_ctor_optional_T_from_optional_U(U val)
|
||||
{
|
||||
direct_test_ctor_optional_T_from_optional_U<T>(val);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void direct_test_ctor_optional_T_from_valued_optional_T(T val)
|
||||
{
|
||||
optional<T> om(val);
|
||||
const optional<T> oc(val);
|
||||
BOOST_TEST(om);
|
||||
BOOST_TEST(oc);
|
||||
|
||||
{
|
||||
optional<T> ox = om;
|
||||
BOOST_TEST(ox);
|
||||
|
||||
optional<T> oy = oc;
|
||||
BOOST_TEST(oy);
|
||||
|
||||
optional<T> oz = optional<T>(val);
|
||||
BOOST_TEST(oz);
|
||||
}
|
||||
{
|
||||
optional<T> ox = {om};
|
||||
BOOST_TEST(ox);
|
||||
|
||||
optional<T> oy = {oc};
|
||||
BOOST_TEST(oy);
|
||||
|
||||
optional<T> oz = {optional<T>(val)};
|
||||
BOOST_TEST(oz);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_ctor_optional_T_from_valued_optional_T(T val)
|
||||
{
|
||||
direct_test_ctor_optional_T_from_valued_optional_T<T>(val);
|
||||
direct_test_ctor_optional_T_from_valued_optional_T<optional<T>>(val);
|
||||
direct_test_ctor_optional_T_from_valued_optional_T<const T>(val);
|
||||
direct_test_ctor_optional_T_from_optional_U<T, T>(val);
|
||||
direct_test_ctor_optional_T_from_optional_U<optional<T>, optional<T>>(val);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void direct_test_inplace_tag_constructor()
|
||||
{
|
||||
{
|
||||
optional<T> ox (boost::in_place_init);
|
||||
BOOST_TEST(ox);
|
||||
}
|
||||
{
|
||||
optional<T> ox {boost::in_place_init};
|
||||
BOOST_TEST(ox);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_inplace_tag_constructor()
|
||||
{
|
||||
direct_test_inplace_tag_constructor<T>();
|
||||
direct_test_inplace_tag_constructor<optional<T>>();
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test_ctor_optional_T_from_empty_optional_T<int, int>();
|
||||
test_ctor_optional_T_from_empty_optional_T<long, long>();
|
||||
test_ctor_optional_T_from_empty_optional_T<std::string, std::string>();
|
||||
test_ctor_optional_T_from_empty_optional_T<JustCopyMoveCtor, JustCopyMoveCtor>();
|
||||
test_ctor_optional_T_from_empty_optional_T<MyBool, MyBool>();
|
||||
|
||||
test_ctor_optional_T_from_empty_optional_T<MyExplicitBool, MyExplicitBool>();
|
||||
|
||||
test_ctor_optional_T_from_empty_optional_T<bool, bool>();
|
||||
test_ctor_optional_T_from_empty_optional_T<Any, Any>();
|
||||
|
||||
test_inplace_tag_constructor<int>();
|
||||
test_inplace_tag_constructor<Any>();
|
||||
test_inplace_tag_constructor<JustDefault>();
|
||||
|
||||
test_ctor_optional_T_from_optional_U<int>(1);
|
||||
test_ctor_optional_T_from_optional_U<long>(1);
|
||||
test_ctor_optional_T_from_optional_U<bool>(MyBool{true});
|
||||
test_ctor_optional_T_from_optional_U<bool>(MyBool{false});
|
||||
test_ctor_optional_T_from_optional_U<MyBool>(true);
|
||||
test_ctor_optional_T_from_optional_U<MyBool>(false);
|
||||
test_ctor_optional_T_from_optional_U<bool>(MyExplicitBool{true});
|
||||
test_ctor_optional_T_from_optional_U<bool>(MyExplicitBool{false});
|
||||
test_ctor_optional_T_from_optional_U<MyExplicitBool>(true);
|
||||
test_ctor_optional_T_from_optional_U<MyExplicitBool>(false);
|
||||
test_ctor_optional_T_from_optional_U<Any>(true);
|
||||
test_ctor_optional_T_from_optional_U<Any>(Any{});
|
||||
|
||||
test_ctor_optional_T_from_valued_optional_T(1);
|
||||
|
||||
optional<MyBool> ob;
|
||||
optional<bool> oa;
|
||||
oa = ob;
|
||||
BOOST_TEST(!oa);
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -45,6 +45,8 @@ void test_optional_of_superconverting_T() // compile-time test
|
||||
superconv<optional<int> > s;
|
||||
superconv<optional<int> > & rs = s;
|
||||
optional<superconv<optional<int> > > os = rs;
|
||||
(void)s;
|
||||
(void)os;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -105,9 +105,42 @@ void test_assign()
|
||||
#endif
|
||||
}
|
||||
|
||||
// begin Boost.Log case
|
||||
|
||||
template <typename CharT>
|
||||
struct basic_formatter
|
||||
{
|
||||
template< typename FunT >
|
||||
basic_formatter(FunT&&) {}
|
||||
|
||||
template< typename FunT >
|
||||
basic_formatter& operator= (FunT&&)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template< typename CharT>
|
||||
struct chained_formatter
|
||||
{
|
||||
};
|
||||
|
||||
void test_boost_log_case()
|
||||
{
|
||||
#ifndef BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
|
||||
boost::optional<basic_formatter<char>> of( boost::in_place(chained_formatter<char>()) );
|
||||
of = boost::in_place(chained_formatter<char>());
|
||||
|
||||
#endif //BOOST_OPTIONAL_NO_INPLACE_FACTORY_SUPPORT
|
||||
}
|
||||
|
||||
// end Boost.Log case
|
||||
|
||||
int main()
|
||||
{
|
||||
test_ctor();
|
||||
test_assign();
|
||||
test_boost_log_case();
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ void test()
|
||||
//BOOST_TEST(v);
|
||||
boost::optional<boost::optional<int>> vv;
|
||||
bool xx = vv?true : false;
|
||||
(void)xx;
|
||||
BOOST_TEST_EQ(*v, 7);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
|
||||
//
|
||||
// Use, modification, and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org/lib/optional for documentation.
|
||||
//
|
||||
// You are welcome to contact the author at:
|
||||
// fernando_cacciola@hotmail.com
|
||||
//
|
||||
#include "boost/optional.hpp"
|
||||
|
||||
//
|
||||
// THIS TEST SHOULD FAIL TO COMPILE
|
||||
//
|
||||
void optional_reference__test_no_converting_initialization()
|
||||
{
|
||||
boost::optional<const int&> o (boost::optional<int>(1));
|
||||
(void)o;
|
||||
}
|
||||
@@ -24,7 +24,13 @@ using boost::none;
|
||||
struct Value
|
||||
{
|
||||
int val;
|
||||
explicit Value(int v) : val(v) {}
|
||||
BOOST_CONSTEXPR explicit Value(int v) : val(v) {}
|
||||
};
|
||||
|
||||
struct Guard
|
||||
{
|
||||
int val;
|
||||
BOOST_CONSTEXPR explicit Guard(int v) : val(v) {}
|
||||
};
|
||||
|
||||
int val(int const& i)
|
||||
@@ -37,6 +43,11 @@ int val(Value const& v)
|
||||
return v.val;
|
||||
}
|
||||
|
||||
int val(Guard const& v)
|
||||
{
|
||||
return v.val;
|
||||
}
|
||||
|
||||
template <typename Tref>
|
||||
optional<Tref&> make_opt_ref(Tref& v)
|
||||
{
|
||||
@@ -47,21 +58,21 @@ template <typename Tval, typename Tref>
|
||||
void test_construct_from_optional_ref()
|
||||
{
|
||||
Tref v1 (1), v2 (2);
|
||||
|
||||
|
||||
optional<Tref&> opt_ref0;
|
||||
optional<Tref&> opt_ref1 (v1);
|
||||
|
||||
|
||||
optional<Tval> opt_val0 (opt_ref0);
|
||||
optional<Tval> opt_val1 (opt_ref1);
|
||||
optional<Tval> opt_val2 (make_opt_ref(v2));
|
||||
|
||||
|
||||
BOOST_TEST (!opt_val0);
|
||||
BOOST_TEST (opt_val1);
|
||||
BOOST_TEST (opt_val2);
|
||||
|
||||
|
||||
BOOST_TEST_EQ (1, val(*opt_val1));
|
||||
BOOST_TEST_EQ (2, val(*opt_val2));
|
||||
|
||||
|
||||
BOOST_TEST (boost::addressof(*opt_val1) != boost::addressof(v1));
|
||||
BOOST_TEST (boost::addressof(*opt_val2) != boost::addressof(v2));
|
||||
}
|
||||
@@ -70,29 +81,121 @@ template <typename Tval, typename Tref>
|
||||
void test_assign_from_optional_ref()
|
||||
{
|
||||
Tref v1 (1), v2 (2);
|
||||
|
||||
|
||||
optional<Tref&> opt_ref0;
|
||||
optional<Tref&> opt_ref1 (v1);
|
||||
|
||||
|
||||
optional<Tval> opt_val0;
|
||||
optional<Tval> opt_val1;
|
||||
optional<Tval> opt_val2;
|
||||
|
||||
|
||||
opt_val0 = opt_ref0;
|
||||
opt_val1 = opt_ref1;
|
||||
opt_val2 = make_opt_ref(v2);
|
||||
|
||||
|
||||
BOOST_TEST (!opt_val0);
|
||||
BOOST_TEST (opt_val1);
|
||||
BOOST_TEST (opt_val2);
|
||||
|
||||
|
||||
BOOST_TEST_EQ (1, val(*opt_val1));
|
||||
BOOST_TEST_EQ (2, val(*opt_val2));
|
||||
|
||||
|
||||
BOOST_TEST (boost::addressof(*opt_val1) != boost::addressof(v1));
|
||||
BOOST_TEST (boost::addressof(*opt_val2) != boost::addressof(v2));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void test_convert_optional_T_to_optional_T_ref()
|
||||
{
|
||||
#ifdef BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
using boost::optional;
|
||||
using boost::in_place_init;
|
||||
|
||||
{ // optional<T>& -> optional<T&>
|
||||
optional<T> ovN, ov1(in_place_init, 1), ov2(in_place_init, 2);
|
||||
|
||||
optional<T&> orN = ovN;
|
||||
optional<T&> or1 = ov1;
|
||||
optional<T&> or2 = ov2;
|
||||
|
||||
BOOST_TEST_EQ (!!orN, !!ovN);
|
||||
BOOST_TEST_EQ (!!or1, !!ov1);
|
||||
BOOST_TEST_EQ (!!or2, !!ov2);
|
||||
|
||||
BOOST_TEST (or1);
|
||||
BOOST_TEST (or2);
|
||||
BOOST_TEST_EQ (val(*or1), 1);
|
||||
BOOST_TEST_EQ (val(*or2), 2);
|
||||
BOOST_TEST (boost::addressof(*or1) == boost::addressof(*ov1));
|
||||
BOOST_TEST (boost::addressof(*or2) == boost::addressof(*ov2));
|
||||
}
|
||||
|
||||
{ // const optional<T>& -> optional<const T&>
|
||||
constexpr optional<T> ovN;
|
||||
constexpr optional<T> ov1(in_place_init, 1);
|
||||
constexpr optional<T> ov2(in_place_init, 2);
|
||||
|
||||
optional<const T&> orN = ovN;
|
||||
optional<const T&> or1 = ov1;
|
||||
optional<const T&> or2 = ov2;
|
||||
|
||||
BOOST_TEST_EQ (!!orN, !!ovN);
|
||||
BOOST_TEST_EQ (!!or1, !!ov1);
|
||||
BOOST_TEST_EQ (!!or2, !!ov2);
|
||||
|
||||
BOOST_TEST (or1);
|
||||
BOOST_TEST (or2);
|
||||
BOOST_TEST_EQ (val(*or1), 1);
|
||||
BOOST_TEST_EQ (val(*or2), 2);
|
||||
BOOST_TEST (boost::addressof(*or1) == boost::addressof(*ov1));
|
||||
BOOST_TEST (boost::addressof(*or2) == boost::addressof(*ov2));
|
||||
}
|
||||
|
||||
{ // optional<const T>& -> optional<const T&>
|
||||
optional<const T> ovN;
|
||||
optional<const T> ov1(in_place_init, 1);
|
||||
optional<const T> ov2(in_place_init, 2);
|
||||
|
||||
optional<const T&> orN = ovN;
|
||||
optional<const T&> or1 = ov1;
|
||||
optional<const T&> or2 = ov2;
|
||||
|
||||
BOOST_TEST_EQ (!!orN, !!ovN);
|
||||
BOOST_TEST_EQ (!!or1, !!ov1);
|
||||
BOOST_TEST_EQ (!!or2, !!ov2);
|
||||
|
||||
BOOST_TEST (or1);
|
||||
BOOST_TEST (or2);
|
||||
BOOST_TEST_EQ (val(*or1), 1);
|
||||
BOOST_TEST_EQ (val(*or2), 2);
|
||||
BOOST_TEST (boost::addressof(*or1) == boost::addressof(*ov1));
|
||||
BOOST_TEST (boost::addressof(*or2) == boost::addressof(*ov2));
|
||||
}
|
||||
|
||||
{ // optional<T>& -> optional<const T&>
|
||||
optional<T> ovN;
|
||||
optional<T> ov1(in_place_init, 1);
|
||||
optional<T> ov2(in_place_init, 2);
|
||||
|
||||
optional<const T&> orN = ovN;
|
||||
optional<const T&> or1 = ov1;
|
||||
optional<const T&> or2 = ov2;
|
||||
|
||||
BOOST_TEST_EQ (!!orN, !!ovN);
|
||||
BOOST_TEST_EQ (!!or1, !!ov1);
|
||||
BOOST_TEST_EQ (!!or2, !!ov2);
|
||||
|
||||
BOOST_TEST (or1);
|
||||
BOOST_TEST (or2);
|
||||
BOOST_TEST_EQ (val(*or1), 1);
|
||||
BOOST_TEST_EQ (val(*or2), 2);
|
||||
BOOST_TEST (boost::addressof(*or1) == boost::addressof(*ov1));
|
||||
BOOST_TEST (boost::addressof(*or2) == boost::addressof(*ov2));
|
||||
}
|
||||
|
||||
#endif // BOOST_OPTIONAL_USES_UNION_IMPLEMENTATION
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
@@ -100,17 +203,21 @@ int main()
|
||||
test_construct_from_optional_ref<int, int const>();
|
||||
test_construct_from_optional_ref<int const, int const>();
|
||||
test_construct_from_optional_ref<int const, int>();
|
||||
|
||||
|
||||
test_construct_from_optional_ref<Value, Value>();
|
||||
test_construct_from_optional_ref<Value, Value const>();
|
||||
test_construct_from_optional_ref<Value const, Value const>();
|
||||
test_construct_from_optional_ref<Value const, Value>();
|
||||
|
||||
|
||||
test_assign_from_optional_ref<int, int>();
|
||||
test_assign_from_optional_ref<int, int const>();
|
||||
|
||||
test_assign_from_optional_ref<Value, Value>();
|
||||
test_assign_from_optional_ref<Value, Value const>();
|
||||
|
||||
test_convert_optional_T_to_optional_T_ref<int>();
|
||||
test_convert_optional_T_to_optional_T_ref<Value>();
|
||||
test_convert_optional_T_to_optional_T_ref<Guard>();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user