From 82d08adf119d9fd2f99fe02d25ff4c5895bb4a6e Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 15 Aug 2024 01:48:31 +0200 Subject: [PATCH 01/16] Drop support for C++03 --- doc/91_relnotes.qbk | 5 ++ include/boost/none_t.hpp | 5 +- .../detail/optional_reference_spec.hpp | 83 ++++++++++--------- include/boost/optional/optional.hpp | 35 ++++---- test/optional_test_msvc_bug_workaround.cpp | 8 +- 5 files changed, 71 insertions(+), 65 deletions(-) diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk index cadccbe..781d406 100644 --- a/doc/91_relnotes.qbk +++ b/doc/91_relnotes.qbk @@ -11,6 +11,11 @@ [section:relnotes Release Notes] +[heading Boost Release 1.87] + +* *Breaking change.* Dropped support for C++03. C++11 is now the required minimum. + + [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/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index b013f0b..3be3d33 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; } + + bool operator!() const BOOST_NOEXCEPT { return ptr_ == 0; } BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() - + 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 + auto map(F f) const -> optional { if (this->has_value()) return f(this->get()); @@ -178,61 +178,62 @@ public: } template - optional::type>::type> flat_map(F f) const + auto flat_map(F f) const -> + optional::type> { 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/optional.hpp b/include/boost/optional/optional.hpp index 99245ff..22221d2 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -60,7 +60,6 @@ #include #include #include -#include #include #include @@ -75,12 +74,15 @@ 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(); + }} // namespace boost::optional_detail namespace boost { @@ -1381,7 +1383,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 +1403,7 @@ class optional } template - optional::type> map(F f) & + optional()(optional_detail::declval()))> map(F f) & { if (this->has_value()) return f(get()); @@ -1411,7 +1412,7 @@ class optional } template - optional::type> map(F f) const& + optional()(optional_detail::declval()))> map(F f) const& { if (this->has_value()) return f(get()); @@ -1420,7 +1421,7 @@ class optional } template - optional::type> map(F f) && + optional()(optional_detail::declval()))> map(F f) && { if (this->has_value()) return f(boost::move(this->get())); @@ -1429,7 +1430,7 @@ class optional } template - optional::type>::type> flat_map(F f) & + optional()(optional_detail::declval()))>::type> flat_map(F f) & { if (this->has_value()) return f(get()); @@ -1438,7 +1439,7 @@ class optional } template - optional::type>::type> flat_map(F f) const& + optional()(optional_detail::declval()))>::type>flat_map(F f) const& { if (this->has_value()) return f(get()); @@ -1447,7 +1448,7 @@ class optional } template - optional::type>::type> flat_map(F f) && + optional()(optional_detail::declval()))>::type>flat_map(F f) && { if (this->has_value()) return f(boost::move(get())); @@ -1466,7 +1467,7 @@ class optional } template - optional::type> map(F f) + optional()(optional_detail::declval()))> map(F f) { if (this->has_value()) return f(get()); @@ -1475,7 +1476,7 @@ class optional } template - optional::type> map(F f) const + optional()(optional_detail::declval()))> map(F f) const { if (this->has_value()) return f(get()); @@ -1484,7 +1485,7 @@ class optional } template - optional::type>::type> flat_map(F f) + optional()(optional_detail::declval()))>::type> flat_map(F f) { if (this->has_value()) return f(get()); @@ -1493,7 +1494,7 @@ class optional } template - optional::type>::type> flat_map(F f) const + optional()(optional_detail::declval()))>::type> flat_map(F f) const { if (this->has_value()) return f(get()); @@ -1505,9 +1506,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/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 +} From 3a8556186ebc778176863b01060043d6aa1d3cc0 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 15 Aug 2024 08:49:21 +0200 Subject: [PATCH 02/16] Drop dependency on Boost.Utility --- doc/90_dependencies.qbk | 3 +-- doc/91_relnotes.qbk | 2 ++ .../boost/optional/detail/optional_relops.hpp | 20 +++++++++---------- include/boost/optional/optional.hpp | 1 - 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/doc/90_dependencies.qbk b/doc/90_dependencies.qbk index 0dab296..d033b08 100644 --- a/doc/90_dependencies.qbk +++ b/doc/90_dependencies.qbk @@ -18,11 +18,10 @@ The implementation uses the following other Boost modules: # config # core # move -# mpl +# predef # static_assert # throw_exception # type_traits -# utility [endsect] diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk index 781d406..9307a24 100644 --- a/doc/91_relnotes.qbk +++ b/doc/91_relnotes.qbk @@ -14,6 +14,8 @@ [heading Boost Release 1.87] * *Breaking change.* Dropped support for C++03. C++11 is now the required minimum. +* Dropped dependency on Boost.Utility. +* A bit faster implementation of some relational operations. [heading Boost Release 1.85] diff --git a/include/boost/optional/detail/optional_relops.hpp b/include/boost/optional/detail/optional_relops.hpp index 1c15578..c7766fc 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 @@ -134,7 +135,7 @@ bool operator == ( optional const& x, none_t ) BOOST_NOEXCEPT template inline bool operator < ( optional const& x, none_t ) -{ return less_pointees(x,optional() ); } +{ 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 22221d2..57ff8ef 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -59,7 +59,6 @@ #include #include #include -#include #include #include From 794e03af308cf714f3852a496bb741b188c55a23 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 15 Aug 2024 10:43:43 +0200 Subject: [PATCH 03/16] Drop dependency on Boost.Predef --- CMakeLists.txt | 2 -- doc/90_dependencies.qbk | 1 - doc/91_relnotes.qbk | 1 + include/boost/optional/detail/experimental_traits.hpp | 1 - test/optional_xconfig_HACK_TO_LIST_PREDEFINED_MACROS.cpp | 6 +++--- 5 files changed, 4 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aba836f..0d5a858 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,11 +18,9 @@ target_link_libraries(boost_optional Boost::config Boost::core Boost::move - Boost::predef Boost::static_assert Boost::throw_exception Boost::type_traits - Boost::utility ) 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 d033b08..e0beee3 100644 --- a/doc/90_dependencies.qbk +++ b/doc/90_dependencies.qbk @@ -18,7 +18,6 @@ The implementation uses the following other Boost modules: # config # core # move -# predef # static_assert # throw_exception # type_traits diff --git a/doc/91_relnotes.qbk b/doc/91_relnotes.qbk index 9307a24..8b1a9e8 100644 --- a/doc/91_relnotes.qbk +++ b/doc/91_relnotes.qbk @@ -15,6 +15,7 @@ * *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. diff --git a/include/boost/optional/detail/experimental_traits.hpp b/include/boost/optional/detail/experimental_traits.hpp index 5667034..24df623 100644 --- a/include/boost/optional/detail/experimental_traits.hpp +++ b/include/boost/optional/detail/experimental_traits.hpp @@ -14,7 +14,6 @@ #include #include -#include #include // The condition to use POD implementation 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 From 6ec468aff6d8dea7b0fcc52962fbe6bf90e4511f Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 15 Aug 2024 10:57:03 +0200 Subject: [PATCH 04/16] Drop explicit bool idiom --- include/boost/optional/detail/optional_reference_spec.hpp | 3 +-- include/boost/optional/optional.hpp | 1 - test/optional_test_convert_assign.cpp | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index 3be3d33..4940a46 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -160,8 +160,7 @@ public: 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; } diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 57ff8ef..72fbd60 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include 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 From 27309c40adb08eb1f1da363328eda256978ea174 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 15 Aug 2024 11:13:44 +0200 Subject: [PATCH 05/16] Drop unused traits --- .../optional/detail/experimental_traits.hpp | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/include/boost/optional/detail/experimental_traits.hpp b/include/boost/optional/detail/experimental_traits.hpp index 24df623..3776551 100644 --- a/include/boost/optional/detail/experimental_traits.hpp +++ b/include/boost/optional/detail/experimental_traits.hpp @@ -52,14 +52,6 @@ #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 - - namespace boost { namespace optional_detail { #ifndef BOOST_OPTIONAL_DETAIL_NO_SPEC_FOR_TRIVIAL_TYPES @@ -81,23 +73,6 @@ struct is_type_trivially_copyable #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 From 346dc03746d71ac7223cc1d150df877b7843a4f7 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 15 Aug 2024 11:42:42 +0200 Subject: [PATCH 06/16] Reimplement trivially semiregular trait --- .../optional/detail/experimental_traits.hpp | 23 +----- include/boost/optional/optional.hpp | 4 -- test/optional_test_experimental_traits.cpp | 70 +++++++++---------- test/optional_test_static_properties.cpp | 56 +++++++-------- 4 files changed, 65 insertions(+), 88 deletions(-) diff --git a/include/boost/optional/detail/experimental_traits.hpp b/include/boost/optional/detail/experimental_traits.hpp index 3776551..4d4abe8 100644 --- a/include/boost/optional/detail/experimental_traits.hpp +++ b/include/boost/optional/detail/experimental_traits.hpp @@ -12,8 +12,6 @@ #ifndef BOOST_OPTIONAL_DETAIL_EXPERIMENTAL_TRAITS_04NOV2017_HPP #define BOOST_OPTIONAL_DETAIL_EXPERIMENTAL_TRAITS_04NOV2017_HPP -#include -#include #include // The condition to use POD implementation @@ -22,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 @@ -34,21 +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 @@ -56,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 && @@ -66,7 +47,7 @@ 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 {}; diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 72fbd60..393eb43 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -22,10 +22,6 @@ #include #endif // BOOST_NO_IOSTREAM -#ifdef BOOST_OPTIONAL_DETAIL_USE_STD_TYPE_TRAITS -# include -#endif - #include #include #include 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_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 From e360de3da52cc3f5fca7347354d969d996150c53 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 15 Aug 2024 11:48:28 +0200 Subject: [PATCH 07/16] Header cleanup --- include/boost/optional/optional.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 393eb43..979ebcc 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include From 411ead088dadd0518bc52161ed87176113167252 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Thu, 15 Aug 2024 21:41:17 +0200 Subject: [PATCH 08/16] Different implementation of map and flat_map --- .../detail/optional_reference_spec.hpp | 7 +-- include/boost/optional/optional.hpp | 44 ++++++++++++++----- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/include/boost/optional/detail/optional_reference_spec.hpp b/include/boost/optional/detail/optional_reference_spec.hpp index 4940a46..9cb2b5c 100644 --- a/include/boost/optional/detail/optional_reference_spec.hpp +++ b/include/boost/optional/detail/optional_reference_spec.hpp @@ -168,7 +168,8 @@ public: bool has_value() const BOOST_NOEXCEPT { return ptr_ != 0; } template - auto map(F f) const -> optional + optional::type> + map(F f) const { if (this->has_value()) return f(this->get()); @@ -177,8 +178,8 @@ public: } template - auto flat_map(F f) const -> - optional::type> + optional::type> + flat_map(F f) const { if (this->has_value()) return f(get()); diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 979ebcc..6be4535 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -76,6 +76,23 @@ struct optional_value_type< ::boost::optional > 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 { @@ -1396,7 +1413,7 @@ class optional } template - optional()(optional_detail::declval()))> map(F f) & + optional::type> map(F f) & { if (this->has_value()) return f(get()); @@ -1405,7 +1422,7 @@ class optional } template - optional()(optional_detail::declval()))> map(F f) const& + optional::type> map(F f) const& { if (this->has_value()) return f(get()); @@ -1414,7 +1431,7 @@ class optional } template - optional()(optional_detail::declval()))> map(F f) && + optional::type> map(F f) && { if (this->has_value()) return f(boost::move(this->get())); @@ -1423,7 +1440,8 @@ class optional } template - optional()(optional_detail::declval()))>::type> flat_map(F f) & + optional::type> + flat_map(F f) & { if (this->has_value()) return f(get()); @@ -1432,7 +1450,8 @@ class optional } template - optional()(optional_detail::declval()))>::type>flat_map(F f) const& + optional::type> + flat_map(F f) const& { if (this->has_value()) return f(get()); @@ -1441,7 +1460,8 @@ class optional } template - optional()(optional_detail::declval()))>::type>flat_map(F f) && + optional::type> + flat_map(F f) && { if (this->has_value()) return f(boost::move(get())); @@ -1460,7 +1480,8 @@ class optional } template - optional()(optional_detail::declval()))> map(F f) + optional::type> + map(F f) { if (this->has_value()) return f(get()); @@ -1469,7 +1490,8 @@ class optional } template - optional()(optional_detail::declval()))> map(F f) const + optional::type> + map(F f) const { if (this->has_value()) return f(get()); @@ -1478,7 +1500,8 @@ class optional } template - optional()(optional_detail::declval()))>::type> flat_map(F f) + optional::type> + flat_map(F f) { if (this->has_value()) return f(get()); @@ -1487,7 +1510,8 @@ class optional } template - optional()(optional_detail::declval()))>::type> flat_map(F f) const + optional::type> + flat_map(F f) const { if (this->has_value()) return f(get()); From 36c33f2e6726ffa3cb36b126781c1bbaa166041b Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 16 Aug 2024 10:37:12 +0200 Subject: [PATCH 09/16] Fix ununsed parameter warning The function returns false w/o using any parameter leading to a warning. Remove the name from the parameter --- include/boost/optional/detail/optional_relops.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/optional/detail/optional_relops.hpp b/include/boost/optional/detail/optional_relops.hpp index c7766fc..dc558ea 100644 --- a/include/boost/optional/detail/optional_relops.hpp +++ b/include/boost/optional/detail/optional_relops.hpp @@ -134,7 +134,7 @@ bool operator == ( optional const& x, none_t ) BOOST_NOEXCEPT template inline -bool operator < ( optional const& x, none_t ) +bool operator < ( optional const&, none_t ) { return false; } template From e1a3501a78e85bb83bbfe0448ce229add4b24e32 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 16 Aug 2024 10:52:32 +0200 Subject: [PATCH 10/16] Rename test_equals_none to test_cmp_none In order to add more tests the new name is more fitting. --- test/Jamfile.v2 | 2 +- ...optional_test_equals_none.cpp => optional_test_cmp_none.cpp} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename test/{optional_test_equals_none.cpp => optional_test_cmp_none.cpp} (100%) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 00bf152..de84f2e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -42,7 +42,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_equals_none.cpp b/test/optional_test_cmp_none.cpp similarity index 100% rename from test/optional_test_equals_none.cpp rename to test/optional_test_cmp_none.cpp From 5fa59b9a3533a017dd30c9536255252c253f229c Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 16 Aug 2024 11:13:45 +0200 Subject: [PATCH 11/16] Add test for all relational operators to `boost::none` --- test/optional_test_cmp_none.cpp | 40 +++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/optional_test_cmp_none.cpp b/test/optional_test_cmp_none.cpp index 1e3157b..691517b 100644 --- a/test/optional_test_cmp_none.cpp +++ b/test/optional_test_cmp_none.cpp @@ -1,4 +1,5 @@ // 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 @@ -36,6 +37,45 @@ void test_equal_to_none_of_noncomparable_T() 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(); From c3b5267506b3a537d55e7a6f0ab82a41b022d431 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 16 Aug 2024 11:44:10 +0200 Subject: [PATCH 12/16] Add C++11 requirements to test Jamfile --- test/Jamfile.v2 | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 00bf152..eb1255d 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,8 +14,24 @@ # akrzemi1@gmail.com # +import config : requires ; import testing ; +project + : requirements + [ 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 ; run optional_test_assign.cpp ; run optional_test_swap.cpp ; From ce03067859f472a62c594f97414c85ba837edd46 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 16 Aug 2024 11:45:19 +0200 Subject: [PATCH 13/16] Add C++11 requirement to CMake --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d5a858..976738b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,7 @@ target_link_libraries(boost_optional Boost::throw_exception Boost::type_traits ) +target_compile_features(boost_optional INTERFACE cxx_std_11) if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") From c6657cc9bd0d36b02eacfa2aa84a16ec44afa804 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 16 Aug 2024 11:53:47 +0200 Subject: [PATCH 14/16] GHA: Fix node version issue Avoid > /__e/node20/bin/node: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /__e/node20/bin/node) See https://github.com/actions/checkout/issues/1590 --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 279a710..72316f2 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: From 8ecf840c33866ea181aade13a5e9b92e73aba986 Mon Sep 17 00:00:00 2001 From: Alexander Grund Date: Fri, 16 Aug 2024 12:07:55 +0200 Subject: [PATCH 15/16] GHA: Use Ubuntu 22.04 for G++11 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 72316f2..05bdc14 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -59,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 From cbc7014edfa7349395b045935d3e7453e832ae75 Mon Sep 17 00:00:00 2001 From: Andrzej Krzemienski Date: Sat, 17 Aug 2024 00:12:45 +0200 Subject: [PATCH 16/16] updated libraries.json --- meta/libraries.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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" }