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 +}