diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 279a710..05bdc14 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,7 @@ on: env: UBSAN_OPTIONS: print_stacktrace=1 + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true jobs: posix: @@ -58,7 +59,7 @@ jobs: address-model: 32,64 - toolset: gcc-11 cxxstd: "03,11,14,17,20" - os: ubuntu-20.04 + os: ubuntu-22.04 install: g++-11-multilib address-model: 32,64 - toolset: gcc-12 diff --git a/CMakeLists.txt b/CMakeLists.txt index aba836f..976738b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,12 +18,11 @@ target_link_libraries(boost_optional Boost::config Boost::core Boost::move - Boost::predef Boost::static_assert Boost::throw_exception Boost::type_traits - Boost::utility ) +target_compile_features(boost_optional INTERFACE cxx_std_11) if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") diff --git a/doc/90_dependencies.qbk b/doc/90_dependencies.qbk index 0dab296..e0beee3 100644 --- a/doc/90_dependencies.qbk +++ b/doc/90_dependencies.qbk @@ -18,11 +18,9 @@ The implementation uses the following other Boost modules: # config # core # move -# mpl # static_assert # throw_exception # type_traits -# utility [endsect] diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk index cadccbe..8b1a9e8 100644 --- a/doc/91_relnotes.qbk +++ b/doc/91_relnotes.qbk @@ -11,6 +11,14 @@ [section:relnotes Release Notes] +[heading Boost Release 1.87] + +* *Breaking change.* Dropped support for C++03. C++11 is now the required minimum. +* Dropped dependency on Boost.Utility. +* Dropped dependency on Boost.Predef. +* A bit faster implementation of some relational operations. + + [heading Boost Release 1.85] * Fixed the implementation for trivial types. Now it is slower, because it always initializes the `T`, but it avoids undefined behavior when `optional` is copied. This fixes [@https://github.com/boostorg/optional/issues/108 issue #108]. diff --git a/include/boost/none_t.hpp b/include/boost/none_t.hpp index 419a728..0f95128 100644 --- a/include/boost/none_t.hpp +++ b/include/boost/none_t.hpp @@ -1,5 +1,5 @@ // Copyright (C) 2003, Fernando Luis Cacciola Carballal. -// Copyright (C) 2014, 2015 Andrzej Krzemienski. +// Copyright (C) 2014, 2024 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 @@ -14,12 +14,11 @@ #define BOOST_NONE_T_17SEP2003_HPP #include -#include #if defined (BOOST_NO_CXX11_RVALUE_REFERENCES) || defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_NO_CXX11_REF_QUALIFIERS) \ || defined(BOOST_NO_CXX11_LAMBDAS) || defined(BOOST_NO_CXX11_DECLTYPE_N3276) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_NO_CXX11_DEFAULTED_MOVES) || defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) -BOOST_PRAGMA_MESSAGE("C++03 support is deprecated in Boost.Optional 1.83 and will be removed in Boost.Optional 1.86.") +#error "Boost.Optional requires C++11 or later. If you have an older C++ version use Boost.Optional version 1.86 or earlier." #endif diff --git a/include/boost/optional/detail/experimental_traits.hpp b/include/boost/optional/detail/experimental_traits.hpp index 5667034..4d4abe8 100644 --- a/include/boost/optional/detail/experimental_traits.hpp +++ b/include/boost/optional/detail/experimental_traits.hpp @@ -12,9 +12,6 @@ #ifndef BOOST_OPTIONAL_DETAIL_EXPERIMENTAL_TRAITS_04NOV2017_HPP #define BOOST_OPTIONAL_DETAIL_EXPERIMENTAL_TRAITS_04NOV2017_HPP -#include -#include -#include #include // The condition to use POD implementation @@ -23,8 +20,6 @@ # define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES #elif defined BOOST_OPTIONAL_CONFIG_NO_SPEC_FOR_TRIVIAL_TYPES # define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES -#elif !defined BOOST_HAS_TRIVIAL_CONSTRUCTOR -# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES #elif !defined BOOST_HAS_TRIVIAL_MOVE_ASSIGN # define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES #elif !defined BOOST_HAS_TRIVIAL_MOVE_CONSTRUCTOR @@ -35,29 +30,6 @@ # define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES #elif !defined BOOST_HAS_TRIVIAL_DESTRUCTOR # define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES -#elif BOOST_WORKAROUND(BOOST_GCC, < 50000) -# define BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES -#endif - -// GCC 5 or higher, or clang with libc++ or clang with libstdc++ 5 or higher -#if __cplusplus >= 201103L -# if BOOST_WORKAROUND(BOOST_GCC, >= 50000) -# define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS -# elif (defined BOOST_CLANG) -# if BOOST_LIB_STD_CXX > 0 -# define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS -# elif BOOST_LIB_STD_GNU >= 441200023 && BOOST_LIB_STD_GNU != 450600023 && BOOST_LIB_STD_GNU != 450600026 && BOOST_LIB_STD_GNU != 460800003 && BOOST_LIB_STD_GNU != 450400026 && BOOST_LIB_STD_GNU != 460700026 -# define BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS -# endif -# endif -#endif - - -#ifndef BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS -# define BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T) BOOST_HAS_TRIVIAL_CONSTRUCTOR(T) -#else -# include -# define BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T) std::is_trivially_default_constructible::value #endif @@ -65,7 +37,7 @@ namespace boost { namespace optional_detail { #ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES template -struct is_type_trivially_copyable +struct is_trivially_semiregular : boost::conditional<(boost::has_trivial_copy_constructor::value && boost::has_trivial_move_constructor::value && boost::has_trivial_destructor::value && @@ -75,30 +47,13 @@ struct is_type_trivially_copyable {}; #else template -struct is_type_trivially_copyable +struct is_trivially_semiregular : boost::conditional<(boost::is_scalar::value && !boost::is_const::value && !boost::is_volatile::value), boost::true_type, boost::false_type>::type {}; #endif - -#ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES -template -struct optional_uses_direct_storage_for_ - : boost::conditional< (is_type_trivially_copyable::value && BOOST_OPTIONAL_DETAIL_HAS_TRIVIAL_CTOR(T)) || - (boost::is_scalar::value && !boost::is_const::value && !boost::is_volatile::value) - , boost::true_type, boost::false_type>::type -{}; -#else -template -struct optional_uses_direct_storage_for_ - : boost::conditional<(boost::is_scalar::value && !boost::is_const::value && !boost::is_volatile::value) - , boost::true_type, boost::false_type>::type -{}; -#endif - - }} // boost::optional_detail #endif diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index b013f0b..9cb2b5c 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2015-2018 Andrzej Krzemienski. +// Copyright (C) 2015-2024 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 @@ -29,15 +29,15 @@ template void prevent_binding_rvalue() { #ifndef BOOST_OPTIONAL_CONFIG_ALLOW_BINDING_TO_RVALUES - BOOST_STATIC_ASSERT_MSG(boost::is_lvalue_reference::value, + BOOST_STATIC_ASSERT_MSG(boost::is_lvalue_reference::value, "binding rvalue references to optional lvalue references is disallowed"); -#endif +#endif } template BOOST_DEDUCED_TYPENAME boost::remove_reference::type& forward_reference(T&& r) { - BOOST_STATIC_ASSERT_MSG(boost::is_lvalue_reference::value, + BOOST_STATIC_ASSERT_MSG(boost::is_lvalue_reference::value, "binding rvalue references to optional lvalue references is disallowed"); return boost::forward(r); } @@ -68,10 +68,10 @@ void prevent_assignment_from_false_const_integral() #ifdef BOOST_OPTIONAL_CONFIG_NO_PROPER_ASSIGN_FROM_CONST_INT // MSVC compiler without rvalue references: we need to disable the assignment from // const integral lvalue reference, as it may be an invalid temporary - BOOST_STATIC_ASSERT_MSG(!is_const_integral::value, + BOOST_STATIC_ASSERT_MSG(!is_const_integral::value, "binding const lvalue references to integral types is disabled in this compiler"); #endif -#endif +#endif } @@ -114,7 +114,7 @@ template class optional : public optional_detail::optional_tag { T* ptr_; - + public: typedef T& value_type; typedef T& reference_type; @@ -122,19 +122,19 @@ public: typedef T& rval_reference_type; typedef T* pointer_type; typedef T* pointer_const_type; - + optional() BOOST_NOEXCEPT : ptr_() {} - optional(none_t) BOOST_NOEXCEPT : ptr_() {} + optional(none_t) BOOST_NOEXCEPT : ptr_() {} template explicit optional(const optional& rhs) BOOST_NOEXCEPT : ptr_(rhs.get_ptr()) {} 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 explicit optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && detail::is_const_integral_bad_for_conversion::value, bool>::type = true) BOOST_NOEXCEPT : ptr_(boost::addressof(rhs)) {} - + template optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && !detail::is_const_integral_bad_for_conversion::value, bool>::type = true) BOOST_NOEXCEPT : ptr_(boost::addressof(rhs)) {} @@ -143,15 +143,15 @@ public: template optional& operator=(const optional& rhs) BOOST_NOEXCEPT { ptr_ = rhs.get_ptr(); return *this; } 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_; } T* get_ptr() const BOOST_NOEXCEPT { return ptr_; } T* operator->() const { BOOST_ASSERT(ptr_); return ptr_; } T& operator*() const { BOOST_ASSERT(ptr_); return *ptr_; } - + T& value() const { if (this->is_initialized()) @@ -159,17 +159,17 @@ public: else throw_exception(bad_optional_access()); } - - bool operator!() const BOOST_NOEXCEPT { return ptr_ == 0; } - BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() - + + explicit operator bool() const BOOST_NOEXCEPT { return ptr_ != 0; } + void reset() BOOST_NOEXCEPT { ptr_ = 0; } bool is_initialized() const BOOST_NOEXCEPT { return ptr_ != 0; } bool has_value() const BOOST_NOEXCEPT { return ptr_ != 0; } - + template - optional::type> map(F f) const + optional::type> + map(F f) const { if (this->has_value()) return f(this->get()); @@ -178,61 +178,62 @@ public: } template - optional::type>::type> flat_map(F f) const + optional::type> + flat_map(F f) const { if (this->has_value()) return f(get()); else return none; } - -#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES - + +#ifndef BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES + optional(T&& /* rhs */) BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); } - + template optional(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) BOOST_NOEXCEPT : ptr_(boost::addressof(r)) { detail::prevent_binding_rvalue(); } - + template optional(bool cond, R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) BOOST_NOEXCEPT : ptr_(cond ? boost::addressof(r) : 0) { detail::prevent_binding_rvalue(); } - + template BOOST_DEDUCED_TYPENAME boost::enable_if, optional&>::type operator=(R&& r) BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); ptr_ = boost::addressof(r); return *this; } - + template void emplace(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); ptr_ = boost::addressof(r); } - + template T& get_value_or(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) const BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); return ptr_ ? *ptr_ : r; } - + template T& value_or(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) const BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); return ptr_ ? *ptr_ : r; } - + template void reset(R&& r, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) BOOST_NOEXCEPT { detail::prevent_binding_rvalue(); ptr_ = boost::addressof(r); } - + template 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 explicit optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && detail::is_const_integral_bad_for_conversion::value, bool>::type = true) BOOST_NOEXCEPT : ptr_(boost::addressof(v)) { } - + template optional(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if_c::value && !detail::is_const_integral_bad_for_conversion::value, bool>::type = true) BOOST_NOEXCEPT : ptr_(boost::addressof(v)) { } - + template optional(bool cond, U& v, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) BOOST_NOEXCEPT : ptr_(cond ? boost::addressof(v) : 0) {} @@ -247,26 +248,26 @@ public: template void emplace(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) BOOST_NOEXCEPT { ptr_ = boost::addressof(v); } - + template T& get_value_or(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) const BOOST_NOEXCEPT { return ptr_ ? *ptr_ : v; } - + template T& value_or(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) const BOOST_NOEXCEPT { return ptr_ ? *ptr_ : v; } - + template void reset(U& v, BOOST_DEDUCED_TYPENAME boost::enable_if, bool>::type = true) BOOST_NOEXCEPT { ptr_ = boost::addressof(v); } - + template T& value_or_eval(F f) const { return ptr_ ? *ptr_ : f(); } - + #endif // BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES }; -template +template void swap ( optional& x, optional& y) BOOST_NOEXCEPT { x.swap(y); diff --git a/include/boost/optional/detail/optional_relops.hpp b/include/boost/optional/detail/optional_relops.hpp index 1c15578..dc558ea 100644 --- a/include/boost/optional/detail/optional_relops.hpp +++ b/include/boost/optional/detail/optional_relops.hpp @@ -1,5 +1,5 @@ // Copyright (C) 2003, 2008 Fernando Luis Cacciola Carballal. -// Copyright (C) 2015 Andrzej Krzemienski. +// Copyright (C) 2015, 2024 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 @@ -16,7 +16,8 @@ namespace boost { // optional's relational operators ( ==, !=, <, >, <=, >= ) have deep-semantics (compare values). -// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointees() in generic code instead. +// WARNING: This is UNLIKE pointers. Use equal_pointees()/less_pointees() in generic code instead, +// to obtain the same semantic for pointers. // @@ -31,7 +32,7 @@ bool operator == ( optional const& x, optional const& y ) template inline bool operator < ( optional const& x, optional const& y ) -{ return less_pointees(x,y); } +{ return !y ? false : (!x ? true : (*x) < (*y)); } template inline @@ -60,12 +61,12 @@ bool operator >= ( optional const& x, optional const& y ) template inline bool operator == ( optional const& x, T const& y ) -{ return equal_pointees(x, optional(y)); } +{ return x && (*x == y); } template inline bool operator < ( optional const& x, T const& y ) -{ return less_pointees(x, optional(y)); } +{ return (!x) || (*x < y); } template inline @@ -94,12 +95,12 @@ bool operator >= ( optional const& x, T const& y ) template inline bool operator == ( T const& x, optional const& y ) -{ return equal_pointees( optional(x), y ); } +{ return y && (x == *y); } template inline bool operator < ( T const& x, optional const& y ) -{ return less_pointees( optional(x), y ); } +{ return y && (x < *y); } template inline @@ -133,8 +134,8 @@ bool operator == ( optional const& x, none_t ) BOOST_NOEXCEPT template inline -bool operator < ( optional const& x, none_t ) -{ return less_pointees(x,optional() ); } +bool operator < ( optional const&, none_t ) +{ return false; } template inline @@ -168,7 +169,7 @@ bool operator == ( none_t , optional const& y ) BOOST_NOEXCEPT template inline bool operator < ( none_t , optional const& y ) -{ return less_pointees(optional() ,y); } +{ return bool(y); } template inline @@ -193,4 +194,3 @@ bool operator >= ( none_t x, optional const& y ) } // namespace boost #endif // header guard - diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 99245ff..6be4535 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -22,20 +22,14 @@ #include #endif // BOOST_NO_IOSTREAM -#ifdef BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS -# include -#endif - #include #include #include -#include #include #include #include #include #include -#include #include #include #include @@ -59,8 +53,6 @@ #include #include #include -#include -#include #include #include @@ -75,12 +67,32 @@ struct optional_value_type { }; -template -struct optional_value_type< ::boost::optional > +template +struct optional_value_type< ::boost::optional > { - typedef T type; + typedef U type; }; +template +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 ()(declval()))> +struct result_of +{ + typedef Rslt type; +}; + +template ::type>::type> +struct result_value_type +{ + typedef Rslt type; +}; + +// optional()(optional_detail::declval()))>::type> + }} // namespace boost::optional_detail namespace boost { @@ -1381,7 +1393,6 @@ class optional } #endif - #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES) template value_type value_or_eval ( F f ) const& @@ -1402,7 +1413,7 @@ class optional } template - optional::type> map(F f) & + optional::type> map(F f) & { if (this->has_value()) return f(get()); @@ -1411,7 +1422,7 @@ class optional } template - optional::type> map(F f) const& + optional::type> map(F f) const& { if (this->has_value()) return f(get()); @@ -1420,7 +1431,7 @@ class optional } template - optional::type> map(F f) && + optional::type> map(F f) && { if (this->has_value()) return f(boost::move(this->get())); @@ -1429,7 +1440,8 @@ class optional } template - optional::type>::type> flat_map(F f) & + optional::type> + flat_map(F f) & { if (this->has_value()) return f(get()); @@ -1438,7 +1450,8 @@ class optional } template - optional::type>::type> flat_map(F f) const& + optional::type> + flat_map(F f) const& { if (this->has_value()) return f(get()); @@ -1447,7 +1460,8 @@ class optional } template - optional::type>::type> flat_map(F f) && + optional::type> + flat_map(F f) && { if (this->has_value()) return f(boost::move(get())); @@ -1466,7 +1480,8 @@ class optional } template - optional::type> map(F f) + optional::type> + map(F f) { if (this->has_value()) return f(get()); @@ -1475,7 +1490,8 @@ class optional } template - optional::type> map(F f) const + optional::type> + map(F f) const { if (this->has_value()) return f(get()); @@ -1484,7 +1500,8 @@ class optional } template - optional::type>::type> flat_map(F f) + optional::type> + flat_map(F f) { if (this->has_value()) return f(get()); @@ -1493,7 +1510,8 @@ class optional } template - optional::type>::type> flat_map(F f) const + optional::type> + flat_map(F f) const { if (this->has_value()) return f(get()); @@ -1505,9 +1523,7 @@ class optional bool has_value() const BOOST_NOEXCEPT { return this->is_initialized() ; } - bool operator!() const BOOST_NOEXCEPT { return !this->is_initialized() ; } - - BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + explicit operator bool() const BOOST_NOEXCEPT { return this->has_value() ; } } ; diff --git a/meta/libraries.json b/meta/libraries.json index a263d7e..0d1fced 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -13,5 +13,5 @@ "Fernando Cacciola ", "Andrzej Krzemienski " ], - "cxxstd": "03" + "cxxstd": "11" } diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index f06d4aa..33c3f25 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -2,6 +2,7 @@ # # Copyright (C) 2003, Fernando Luis Cacciola Carballal. # Copyright (C) 2014 - 2017 Andrzej Krzemienski +# Copyright (C) 2024 Alexander Grund # # Use, modification, and distribution is subject to the Boost Software # License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -13,9 +14,24 @@ # akrzemi1@gmail.com # +import config : requires ; import testing ; -project : requirements /boost/optional//boost_optional ; +project + : requirements + /boost/optional//boost_optional + [ requires + cxx11_decltype + cxx11_defaulted_functions + cxx11_defaulted_moves + cxx11_deleted_functions + cxx11_explicit_conversion_operators + cxx11_noexcept + cxx11_rvalue_references + cxx11_variadic_templates + ] + ; + run optional_test.cpp : : : /boost/bind//boost_bind /boost/mpl//boost_mpl ; run optional_test_assign.cpp ; @@ -44,7 +60,7 @@ run optional_test_inplace_factory.cpp ; run optional_test_io.cpp ; run optional_test_move.cpp ; run optional_test_noexcept_move.cpp ; -run optional_test_equals_none.cpp ; +run optional_test_cmp_none.cpp ; run optional_test_value_access.cpp ; run optional_test_emplace.cpp ; run optional_test_minimum_requirements.cpp ; diff --git a/test/optional_test_cmp_none.cpp b/test/optional_test_cmp_none.cpp new file mode 100644 index 0000000..691517b --- /dev/null +++ b/test/optional_test_cmp_none.cpp @@ -0,0 +1,83 @@ +// Copyright (C) 2014 Andrzej Krzemienski. +// Copyright (C) 2024 Alexander Grund +// +// 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" + +#ifdef BOOST_BORLANDC +#pragma hdrstop +#endif + +#include "boost/core/lightweight_test.hpp" +#include "boost/none.hpp" + + +struct SemiRegular // no operator== +{ +private: void operator==(SemiRegular const&) const {} +private: void operator!=(SemiRegular const&) const {} +}; + +void test_equal_to_none_of_noncomparable_T() +{ + boost::optional i = SemiRegular(); + boost::optional o; + + BOOST_TEST(i != boost::none); + BOOST_TEST(boost::none != i); + BOOST_TEST(o == boost::none); + BOOST_TEST(boost::none == o); +} + +void test_comparison_to_none() +{ + using boost::none; + boost::optional i = SemiRegular(); + // the default ordering of optional is{ boost::none, 0, 1, 2, ... } + // Hence boost::none < i for any engaged i + // and all others operators ( ==, !=, <, <=, >, >= ) follow + + BOOST_TEST(!(i == none)); + BOOST_TEST(i != none); + BOOST_TEST(!(i < none)); + BOOST_TEST(!(i <= none)); + BOOST_TEST(i > none); + BOOST_TEST(i >= none); + // Comparison is symmetric + BOOST_TEST(!(none == i)); + BOOST_TEST(none != i); + BOOST_TEST(none < i); + BOOST_TEST(none <= i); + BOOST_TEST(!(none > i)); + BOOST_TEST(!(none >= i)); + + // An un-engaged optional is always equal to none + boost::optional o; + BOOST_TEST(o == none); + BOOST_TEST(!(o != none)); + BOOST_TEST(!(o < none)); + BOOST_TEST(o <= none); + BOOST_TEST(!(o > none)); + BOOST_TEST(o >= none); + // Comparison is symmetric + BOOST_TEST(none == o); + BOOST_TEST(!(none != o)); + BOOST_TEST(!(none < o)); + BOOST_TEST(none <= o); + BOOST_TEST(!(none > o)); + BOOST_TEST(none >= o); +} + +int main() +{ + test_equal_to_none_of_noncomparable_T(); + return boost::report_errors(); +} diff --git a/test/optional_test_convert_assign.cpp b/test/optional_test_convert_assign.cpp index f0366dc..5e1ceda 100644 --- a/test/optional_test_convert_assign.cpp +++ b/test/optional_test_convert_assign.cpp @@ -25,8 +25,7 @@ struct implicit_bool_conv struct explicit_bool_conv { - bool operator!() const BOOST_NOEXCEPT { return false; } - BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() + explicit operator bool() const BOOST_NOEXCEPT { return true; } }; template diff --git a/test/optional_test_equals_none.cpp b/test/optional_test_equals_none.cpp deleted file mode 100644 index 1e3157b..0000000 --- a/test/optional_test_equals_none.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2014 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" - -#ifdef BOOST_BORLANDC -#pragma hdrstop -#endif - -#include "boost/core/lightweight_test.hpp" -#include "boost/none.hpp" - - -struct SemiRegular // no operator== -{ -private: void operator==(SemiRegular const&) const {} -private: void operator!=(SemiRegular const&) const {} -}; - -void test_equal_to_none_of_noncomparable_T() -{ - boost::optional i = SemiRegular(); - boost::optional o; - - BOOST_TEST(i != boost::none); - BOOST_TEST(boost::none != i); - BOOST_TEST(o == boost::none); - BOOST_TEST(boost::none == o); -} - -int main() -{ - test_equal_to_none_of_noncomparable_T(); - return boost::report_errors(); -} diff --git a/test/optional_test_experimental_traits.cpp b/test/optional_test_experimental_traits.cpp index 5088b4a..eb8a736 100644 --- a/test/optional_test_experimental_traits.cpp +++ b/test/optional_test_experimental_traits.cpp @@ -43,9 +43,9 @@ struct DeletedDefault }; namespace boost { namespace optional_config { - + template <> struct optional_uses_direct_storage_for : boost::true_type {}; - + }} struct CustDtor @@ -78,47 +78,47 @@ void test_type_traits() // this only tests if type traits are implemented correctly BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for )); - + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for )); - + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for > )); - + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for > )); - - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); - + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular )); + + #ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for > )); BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for, double> > )); - - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable, double> > )); - - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); -#endif + + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular, double> > )); + + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular > )); +#endif BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for > )); - - BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable )); - BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable )); - BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable )); - BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable > )); + + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular > )); } void test_trivial_copyability() @@ -127,16 +127,16 @@ void test_trivial_copyability() BOOST_TEST_TRAIT_TRUE((boost::is_base_of, boost::optional > )); BOOST_TEST_TRAIT_TRUE((boost::is_base_of, boost::optional > )); BOOST_TEST_TRAIT_FALSE((boost::is_base_of, boost::optional > )); - + #ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > > )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable, double> > > )); - - BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular > > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular, double> > > )); + + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular > )); #endif } diff --git a/test/optional_test_msvc_bug_workaround.cpp b/test/optional_test_msvc_bug_workaround.cpp index 126e885..8d37068 100644 --- a/test/optional_test_msvc_bug_workaround.cpp +++ b/test/optional_test_msvc_bug_workaround.cpp @@ -29,13 +29,15 @@ void test() { #if (!defined BOOST_NO_CXX11_RVALUE_REFERENCES) boost::optional v = Wrapper(); - BOOST_TEST(v); + //BOOST_TEST(v); + boost::optional> vv; + bool xx = vv?true : false; BOOST_TEST_EQ(*v, 7); #endif -} +} int main() { test(); return boost::report_errors(); -} \ No newline at end of file +} diff --git a/test/optional_test_static_properties.cpp b/test/optional_test_static_properties.cpp index 5dc1053..90cd643 100644 --- a/test/optional_test_static_properties.cpp +++ b/test/optional_test_static_properties.cpp @@ -43,9 +43,9 @@ struct DeletedDefault }; namespace boost { namespace optional_config { - + template <> struct optional_uses_direct_storage_for : boost::true_type {}; - + }} struct CustDtor @@ -78,40 +78,40 @@ void test_type_traits() // this only tests if type traits are implemented correctly BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for )); - + BOOST_TEST_TRAIT_TRUE(( boost::optional_config::optional_uses_direct_storage_for )); - + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for > )); - + BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for > )); - - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); + + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for > )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for, double> > )); #ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES - - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable, double> > )); - -#endif + + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular, double> > )); + +#endif BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for )); BOOST_TEST_TRAIT_FALSE(( boost::optional_config::optional_uses_direct_storage_for > )); - - BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable )); - BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable )); - BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable )); - BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable > )); + + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular > )); } void test_trivial_copyability() @@ -120,18 +120,18 @@ void test_trivial_copyability() BOOST_TEST_TRAIT_TRUE((boost::is_base_of, boost::optional > )); BOOST_TEST_TRAIT_TRUE((boost::is_base_of, boost::optional > )); BOOST_TEST_TRAIT_FALSE((boost::is_base_of, boost::optional > )); - + #ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); - BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_type_trivially_copyable > )); - - BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular > )); + BOOST_TEST_TRAIT_TRUE(( boost::optional_detail::is_trivially_semiregular > )); + + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular > )); #endif - BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable > )); - BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable > > )); - BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_type_trivially_copyable, double> > > )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular > )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular > > )); + BOOST_TEST_TRAIT_FALSE(( boost::optional_detail::is_trivially_semiregular, double> > > )); } #endif diff --git a/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp b/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp index 202c7ef..a3e7a68 100644 --- a/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp +++ b/test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp @@ -11,7 +11,7 @@ #include "boost/core/lightweight_test.hpp" #include "boost/optional/detail/optional_config.hpp" -#include "boost/predef.h" +//#include "boost/predef.h" #include int main() @@ -19,13 +19,13 @@ int main() #if defined(__GNUC__) std::string emptys; - + #ifdef BOOST_INTEL_CXX_VERSION BOOST_TEST_EQ(emptys, "HAS INTEL INSIDE"); #else BOOST_TEST_EQ(emptys, "NO INTEL INSIDE"); #endif - + #if !defined BOOST_NO_CXX11_RVALUE_REFERENCES BOOST_TEST_EQ(emptys, "HAS RVALUE REFS"); #else