https://gcc.gnu.org/g:8b95d5f5b22621da6a5f0d6e07e7d9bf8d270a6d
commit r16-8429-g8b95d5f5b22621da6a5f0d6e07e7d9bf8d270a6d Author: Tomasz Kamiński <[email protected]> Date: Thu Apr 2 12:00:01 2026 +0200 libstdc++: Updated inplace_vector::try_ functions per P3981R2 and P4022R0. This paper removes the try_append_range from inplace_vector and changes the return type of try_emplace_back and try_push_back to optional<_Tp&> per: P4022R0: Remove try_append_range from inplace_vector for now. P3981R2: Better return types in std::inplace_vector and std::exception_ptr_cast. The test are also expanded to cover type Y, that is convertible to optional<Y&>, and require return type to be constructed using in_place. libstdc++-v3/ChangeLog: * include/bits/version.def (inplace_vector): Bump to 202603. * include/bits/version.h: Regenerate. * include/std/inplace_vector (inplace_vector::try_emplace_back) (inplace_vector::try_push_back): Change return type to optional<_Tp&> and adjust implementation accordingly. (inplace_vector::try_append_range): Remove. * include/debug/inplace_vector (inplace_vector::try_emplace_back) (inplace_vector::try_push_back, inplace_vector::try_append_range): Likewise. * testsuite/23_containers/inplace_vector/modifiers/single_insert.cc: Updated check for the optional<T&> return. Added test for type convertible to optional<T&> * testsuite/23_containers/inplace_vector/debug/invalidation/try_emplace_back.cc: Use has_value() to check if engaged optional is returned. * testsuite/23_containers/inplace_vector/debug/invalidation/try_push_back.cc: Likewise. * testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc: Remove try_append_range tests. * testsuite/23_containers/inplace_vector/debug/invalidation/try_append_range.cc: Removed. * testsuite/23_containers/inplace_vector/version.cc: Updated expected feature test macro value. Reviewed-by: Jonathan Wakely <[email protected]> Signed-off-by: Tomasz Kamiński <[email protected]> Diff: --- libstdc++-v3/include/bits/version.def | 5 +- libstdc++-v3/include/bits/version.h | 4 +- libstdc++-v3/include/debug/inplace_vector | 26 +++----- libstdc++-v3/include/std/inplace_vector | 70 ++++++---------------- .../debug/invalidation/try_append_range.cc | 45 -------------- .../debug/invalidation/try_emplace_back.cc | 2 +- .../debug/invalidation/try_push_back.cc | 4 +- .../inplace_vector/modifiers/multi_insert.cc | 46 -------------- .../inplace_vector/modifiers/single_insert.cc | 41 +++++++++---- .../23_containers/inplace_vector/version.cc | 4 +- 10 files changed, 66 insertions(+), 181 deletions(-) diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index ada8da88bc52..998223306e25 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -2223,9 +2223,12 @@ ftms = { }; ftms = { + // 202406 P0843R14 inplace_vector + // 202603 P3981R2 Better return types in std::inplace_vector and std::exception_ptr_cast + // P4022R0 Remove try_append_range from inplace_vector for now name = inplace_vector; values = { - v = 202406; + v = 202603; cxxmin = 26; }; }; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 0490e79dd416..cb3b9b0997e8 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -2488,9 +2488,9 @@ #if !defined(__cpp_lib_inplace_vector) # if (__cplusplus > 202302L) -# define __glibcxx_inplace_vector 202406L +# define __glibcxx_inplace_vector 202603L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_inplace_vector) -# define __cpp_lib_inplace_vector 202406L +# define __cpp_lib_inplace_vector 202603L # endif # endif #endif /* !defined(__cpp_lib_inplace_vector) */ diff --git a/libstdc++-v3/include/debug/inplace_vector b/libstdc++-v3/include/debug/inplace_vector index 750b0a7343ca..e579e8636f98 100644 --- a/libstdc++-v3/include/debug/inplace_vector +++ b/libstdc++-v3/include/debug/inplace_vector @@ -338,11 +338,12 @@ namespace __debug } template<typename... _Args> - constexpr _Tp* + constexpr optional<_Tp&> try_emplace_back(_Args&&... __args) { auto __end = _Base::cend(); - _Tp* __res = _Base::try_emplace_back(std::forward<_Args>(__args)...); + optional<_Tp&> __res + = _Base::try_emplace_back(std::forward<_Args>(__args)...); if (__res) this->_M_invalidate_if(_Equal(__end)); @@ -350,11 +351,11 @@ namespace __debug return __res; } - constexpr _Tp* + constexpr optional<_Tp&> try_push_back(const _Tp& __x) { const auto __end = _Base::cend(); - _Tp* __res = _Base::try_push_back(__x); + optional<_Tp&> __res = _Base::try_push_back(__x); if (__res) this->_M_invalidate_if(_Equal(__end)); @@ -362,11 +363,11 @@ namespace __debug return __res; } - constexpr _Tp* + constexpr optional<_Tp&> try_push_back(_Tp&& __x) { const auto __end = _Base::cend(); - _Tp* __res = _Base::try_push_back(std::move(__x)); + optional<_Tp&> __res = _Base::try_push_back(std::move(__x)); if (__res) this->_M_invalidate_if(_Equal(__end)); @@ -374,19 +375,6 @@ namespace __debug return __res; } - template<__detail::__container_compatible_range<_Tp> _Rg> - constexpr ranges::borrowed_iterator_t<_Rg> - try_append_range(_Rg&& __rg) - { - const auto __size = size(); - const auto __end = _Base::cend(); - auto __res = _Base::try_append_range(__rg); - if (size() != __size) - this->_M_invalidate_if(_Equal(__end)); - - return __res; - } - template<typename... _Args> constexpr _Tp& unchecked_emplace_back(_Args&&... __args) diff --git a/libstdc++-v3/include/std/inplace_vector b/libstdc++-v3/include/std/inplace_vector index c22a9e1f9b40..5ad92332a02c 100644 --- a/libstdc++-v3/include/std/inplace_vector +++ b/libstdc++-v3/include/std/inplace_vector @@ -38,6 +38,7 @@ #ifdef __glibcxx_inplace_vector // C++ >= 26 #include <compare> #include <initializer_list> +#include <optional> #include <bits/stdexcept_throw.h> #include <bits/range_access.h> #include <bits/ranges_base.h> // borrowed_iterator_t, __detail::__container_compatible_range @@ -550,63 +551,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } template<typename... _Args> - constexpr _Tp* + constexpr optional<_Tp&> try_emplace_back(_Args&&... __args) { if (_M_size >= _Nm) [[unlikely]] - return nullptr; - auto& __r = unchecked_emplace_back(std::forward<_Args>(__args)...); - return __builtin_addressof(__r); + return nullopt; + return optional<_Tp&>(in_place, + unchecked_emplace_back(std::forward<_Args>(__args)...)); } - constexpr _Tp* + constexpr optional<_Tp&> try_push_back(const _Tp& __x) { if (_M_size >= _Nm) [[unlikely]] - return nullptr; - return __builtin_addressof(unchecked_emplace_back(__x)); + return nullopt; + return optional<_Tp&>(in_place, unchecked_emplace_back(__x)); } - constexpr _Tp* + constexpr optional<_Tp&> try_push_back(_Tp&& __x) { if (_M_size >= _Nm) [[unlikely]] - return nullptr; - return __builtin_addressof(unchecked_emplace_back(std::move(__x))); + return nullopt; + return optional<_Tp&>(in_place, unchecked_emplace_back(std::move(__x))); } - template<__detail::__container_compatible_range<_Tp> _Rg> - constexpr ranges::borrowed_iterator_t<_Rg> - try_append_range(_Rg&& __rg) - { - if constexpr (ranges::sized_range<_Rg>) - { - auto __n = ranges::distance(__rg); - if (__n == 0) [[unlikely]] - return ranges::begin(__rg); - - const auto __end = data() + _M_size; - const size_t __avail = _Nm - size(); - if (__n <= __avail) - _M_size += size_type(__n); - else - { - __n = __avail; - _M_size = _Nm; - } - return ranges::uninitialized_copy_n( - ranges::begin(__rg), __n, - __end, unreachable_sentinel).in; - } - else - { - ranges::subrange<pointer> __tail(data() + _M_size, data() + _Nm); - auto [__in, __out] = ranges::uninitialized_copy(__rg, __tail); - _M_size = __out - data(); - return std::move(__in); - } - } - template<typename... _Args> constexpr _Tp& unchecked_emplace_back(_Args&&... __args) @@ -1208,22 +1177,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { __builtin_trap(); } template<typename... _Args> - constexpr _Tp* + constexpr optional<_Tp&> try_emplace_back(_Args&&...) - { return nullptr; } + { return nullopt; } - constexpr _Tp* + constexpr optional<_Tp&> try_push_back(const _Tp&) - { return nullptr; } + { return nullopt; } - constexpr _Tp* + constexpr optional<_Tp&> try_push_back(_Tp&&) - { return nullptr; } - - template<__detail::__container_compatible_range<_Tp> _Rg> - constexpr ranges::borrowed_iterator_t<_Rg> - try_append_range(_Rg&& __rg) - { return ranges::begin(__rg); } + { return nullopt; } template<typename... _Args> [[noreturn]] diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/debug/invalidation/try_append_range.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/debug/invalidation/try_append_range.cc deleted file mode 100644 index ae4ac418f501..000000000000 --- a/libstdc++-v3/testsuite/23_containers/inplace_vector/debug/invalidation/try_append_range.cc +++ /dev/null @@ -1,45 +0,0 @@ -// { dg-do run { target c++26 } } - -#include <debug/inplace_vector> -#include <testsuite_hooks.h> - -using __gnu_debug::inplace_vector; - -void test01() -{ - inplace_vector<int, 100> v(10, 17); - inplace_vector<int, 10> v1(10, 19); - - auto before = v.begin() + 6; - auto last = v.end(); - auto end = last--; - - v.try_append_range(v1); - - VERIFY(before._M_dereferenceable()); - VERIFY(last._M_dereferenceable()); - VERIFY(end._M_singular()); -} - -void test02() -{ - inplace_vector<int, 100> v(10, 17); - inplace_vector<int, 0> v1; - - auto before = v.begin() + 6; - auto last = v.end(); - auto end = last--; - - v.try_append_range(v1); - - VERIFY(before._M_dereferenceable()); - VERIFY(last._M_dereferenceable()); - VERIFY(!end._M_singular()); -} - -int main() -{ - test01(); - test02(); - return 0; -} diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/debug/invalidation/try_emplace_back.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/debug/invalidation/try_emplace_back.cc index f7c8c7a9ba20..606d478a0dce 100644 --- a/libstdc++-v3/testsuite/23_containers/inplace_vector/debug/invalidation/try_emplace_back.cc +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/debug/invalidation/try_emplace_back.cc @@ -13,7 +13,7 @@ void test01() auto last = v.end(); auto end = last--; - VERIFY( v.try_emplace_back(42) != nullptr ); + VERIFY( v.try_emplace_back(42).has_value() ); VERIFY(before._M_dereferenceable()); VERIFY(last._M_dereferenceable()); diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/debug/invalidation/try_push_back.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/debug/invalidation/try_push_back.cc index 04fc010e5003..96af2b65b725 100644 --- a/libstdc++-v3/testsuite/23_containers/inplace_vector/debug/invalidation/try_push_back.cc +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/debug/invalidation/try_push_back.cc @@ -14,7 +14,7 @@ void test01() auto last = v.end(); auto end = last--; - VERIFY( v.try_push_back(42) != nullptr ); + VERIFY( v.try_push_back(42).has_value() ); VERIFY(before._M_dereferenceable()); VERIFY(last._M_dereferenceable()); @@ -30,7 +30,7 @@ void test02() auto last = v.end(); auto end = last--; - VERIFY( v.try_push_back(std::move(vv)) != nullptr ); + VERIFY( v.try_push_back(std::move(vv)).has_value() ); VERIFY(before._M_dereferenceable()); VERIFY(last._M_dereferenceable()); diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc index 454163892add..e5a482cdc65d 100644 --- a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/multi_insert.cc @@ -54,16 +54,6 @@ test_add_to_full_it() std::inplace_vector<T, N> v(std::from_range, std::span(a, a+N)); - Range r1(a, a); - auto rit1 = v.try_append_range(r1); - VERIFY( eq<T>(v, {a, N}) ); - VERIFY( rit1.base() == a ); - - SizedRange r2(a, a); - auto rit2 = v.try_append_range(r2); - VERIFY( eq<T>(v, {a, N}) ); - VERIFY( rit2.base() == a ); - v.append_range(Range(a, a)); VERIFY( eq<T>(v, {a, N}) ); v.append_range(SizedRange(a, a)); @@ -93,17 +83,6 @@ test_add_to_full_it() VERIFY( eq<T>(v, {a, N}) ); VERIFY( it == v.begin() ); - // Inserting non-empty range - Range r3(a+3, a+5); - auto rit3 = v.try_append_range(r3); - VERIFY( eq<T>(v, {a, N}) ); - VERIFY( rit3.base() == a+3 ); - - SizedRange r4(a+2, a+5); - auto rit4 = v.try_append_range(r4); - VERIFY( eq<T>(v, {a, N}) ); - VERIFY( rit4.base() == a+2 ); - #ifdef __cpp_exceptions #ifndef __cpp_lib_constexpr_exceptions if consteval { @@ -265,30 +244,6 @@ test_append_range() #endif } -template<typename Range> -constexpr void -test_try_append_range() -{ - using T = std::ranges::range_value_t<Range>; - T a[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25}; - - std::inplace_vector<T, 20> v; - Range r1 = Range(a, a+10); - auto it1 = v.try_append_range(r1); - VERIFY( eq<T>(v, {a, 10}) ); - VERIFY( it1.base() == a+10 ); - - Range r2 = Range(a+10, a+15); - auto it2 = v.try_append_range(r2); - VERIFY( eq<T>(v, {a, 15}) ); - VERIFY( it2.base() == a+15 ); - - Range r3 = Range(a+15, a+25); - auto it3 = v.try_append_range(r3); - VERIFY( eq<T>(v, {a, 20}) ); - VERIFY( it3.base() == a+20 ); -} - template<typename Range> constexpr void test_insert_range() @@ -357,7 +312,6 @@ constexpr void do_test_ranges() { test_append_range<Range>(); - test_try_append_range<Range>(); test_insert_range<Range>(); } diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert.cc index 92bd765982e2..245af9288009 100644 --- a/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert.cc +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/modifiers/single_insert.cc @@ -3,6 +3,7 @@ #include <inplace_vector> #include <span> +#include <optional> #include <testsuite_hooks.h> struct X @@ -18,6 +19,20 @@ struct X friend auto operator<=>(const X&, const X&) = default; }; +// Type that is convertible to optional<Y&> +struct Y +{ + Y() = default; + constexpr Y(int p) : v(p) {} + + constexpr operator std::optional<Y&>() + { return std::nullopt; } + + int v; + + friend auto operator<=>(const Y&, const Y&) = default; +}; + template<typename T, typename V, size_t N> constexpr bool eq(const std::inplace_vector<V, N>& l, std::span<const T> r) { @@ -40,11 +55,11 @@ test_add_to_full() std::inplace_vector<T, N> v(std::from_range, std::span(a, a+N)); - VERIFY( v.try_emplace_back(1) == nullptr ); + VERIFY( !v.try_emplace_back(1).has_value() ); VERIFY( eq<T>(v, {a, N}) ); - VERIFY( v.try_push_back(T(1)) == nullptr ); + VERIFY( !v.try_push_back(T(1)).has_value() ); VERIFY( eq<T>(v, {a, N}) ); - VERIFY( v.try_push_back(c) == nullptr ); + VERIFY( !v.try_push_back(c).has_value() ); VERIFY( eq<T>(v, {a, N}) ); #ifdef __cpp_exceptions @@ -149,15 +164,18 @@ test_inserts() v.unchecked_push_back(c); VERIFY( eq<T>(v, {a+3, 6}) ); - T* ptr = v.try_emplace_back(7); + std::optional<T&> opt = v.try_emplace_back(7); VERIFY( eq<T>(v, {a+3, 7}) ); - VERIFY( ptr = &v.back() ); - ptr = v.try_push_back(T(8)); + VERIFY( opt.has_value() ); + VERIFY( &*opt == &v.back() ); + opt = v.try_push_back(T(8)); VERIFY( eq<T>(v, {a+3, 8}) ); - VERIFY( ptr = &v.back() ); - ptr = v.try_push_back(c); + VERIFY( opt.has_value() ); + VERIFY( &*opt == &v.back() ); + opt = v.try_push_back(c); VERIFY( eq<T>(v, {a+3, 9}) ); - VERIFY( ptr = &v.back() ); + VERIFY( opt.has_value() ); + VERIFY( &*opt == &v.back() ); auto it = v.emplace(v.end(), 10); VERIFY( eq<T>(v, {a+3, 10}) ); @@ -195,12 +213,15 @@ int main() auto test_all = [] { test_add_to_full<0, int>(); test_add_to_full<0, X>(); + test_add_to_full<0, Y>(); test_add_to_full<4, int>(); + test_add_to_full<4, Y>(); test_inserts<int>(); + test_inserts<Y>(); #ifdef __cpp_lib_constexpr_inplace_vector -#error uncomemnt test_inserts<X>() +#error enable tests bellow #endif if ! consteval { test_add_to_full<4, X>(); diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/version.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/version.cc index a5bbdb8464be..493e86dc6dd2 100644 --- a/libstdc++-v3/testsuite/23_containers/inplace_vector/version.cc +++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/version.cc @@ -5,7 +5,7 @@ #ifndef __cpp_lib_inplace_vector # error "Feature-test macro for inplace_vector missing in <inplace_vector>" -#elif __cpp_lib_inplace_vector != 202406L +#elif __cpp_lib_inplace_vector != 202603L # error "Feature-test macro for inplace_vector has wrong value in <inplace_vector>" #endif @@ -15,6 +15,6 @@ #ifndef __cpp_lib_inplace_vector # error "Feature-test macro for inplace_vector missing in <version>" -#elif __cpp_lib_inplace_vector != 202406L +#elif __cpp_lib_inplace_vector != 202603L # error "Feature-test macro for inplace_vector has wrong value in <version>" #endif
