aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include/bits
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3/include/bits')
-rw-r--r--libstdc++-v3/include/bits/iterator_concepts.h35
-rw-r--r--libstdc++-v3/include/bits/vector.tcc138
2 files changed, 112 insertions, 61 deletions
diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
index 1555c37..6802582 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -771,19 +771,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& invocable<_Fn, iter_reference_t<_Is>...>
using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Is>...>;
+ namespace __detail
+ {
+ template<typename _Iter, typename _Proj>
+ struct __projected
+ {
+ struct __type
+ {
+ using value_type = remove_cvref_t<indirect_result_t<_Proj&, _Iter>>;
+ indirect_result_t<_Proj&, _Iter> operator*() const; // not defined
+ };
+ };
+
+ template<weakly_incrementable _Iter, typename _Proj>
+ struct __projected<_Iter, _Proj>
+ {
+ struct __type
+ {
+ using value_type = remove_cvref_t<indirect_result_t<_Proj&, _Iter>>;
+ using difference_type = iter_difference_t<_Iter>;
+ indirect_result_t<_Proj&, _Iter> operator*() const; // not defined
+ };
+ };
+ } // namespace __detail
+
/// [projected], projected
template<indirectly_readable _Iter,
indirectly_regular_unary_invocable<_Iter> _Proj>
- struct projected
- {
- using value_type = remove_cvref_t<indirect_result_t<_Proj&, _Iter>>;
-
- indirect_result_t<_Proj&, _Iter> operator*() const; // not defined
- };
-
- template<weakly_incrementable _Iter, typename _Proj>
- struct incrementable_traits<projected<_Iter, _Proj>>
- { using difference_type = iter_difference_t<_Iter>; };
+ using projected = __detail::__projected<_Iter, _Proj>::__type;
// [alg.req], common algorithm requirements
diff --git a/libstdc++-v3/include/bits/vector.tcc b/libstdc++-v3/include/bits/vector.tcc
index acd11e2..cda52fb 100644
--- a/libstdc++-v3/include/bits/vector.tcc
+++ b/libstdc++-v3/include/bits/vector.tcc
@@ -458,73 +458,109 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_realloc_insert(iterator __position, const _Tp& __x)
#endif
{
- const size_type __len =
- _M_check_len(size_type(1), "vector::_M_realloc_insert");
+ const size_type __len = _M_check_len(1u, "vector::_M_realloc_insert");
pointer __old_start = this->_M_impl._M_start;
pointer __old_finish = this->_M_impl._M_finish;
const size_type __elems_before = __position - begin();
pointer __new_start(this->_M_allocate(__len));
pointer __new_finish(__new_start);
- __try
+
+ // RAII guard for allocated storage.
+ struct _Guard
+ {
+ pointer _M_storage; // Storage to deallocate
+ size_type _M_len;
+ _Tp_alloc_type& _M_alloc;
+
+ _GLIBCXX20_CONSTEXPR
+ _Guard(pointer __s, size_type __l, _Tp_alloc_type& __a)
+ : _M_storage(__s), _M_len(__l), _M_alloc(__a)
+ { }
+
+ _GLIBCXX20_CONSTEXPR
+ ~_Guard()
{
- // The order of the three operations is dictated by the C++11
- // case, where the moves could alter a new element belonging
- // to the existing vector. This is an issue only for callers
- // taking the element by lvalue ref (see last bullet of C++11
- // [res.on.arguments]).
- _Alloc_traits::construct(this->_M_impl,
- __new_start + __elems_before,
+ if (_M_storage)
+ __gnu_cxx::__alloc_traits<_Tp_alloc_type>::
+ deallocate(_M_alloc, _M_storage, _M_len);
+ }
+
+ private:
+ _Guard(const _Guard&);
+ };
+ _Guard __guard(__new_start, __len, _M_impl);
+
+ // The order of the three operations is dictated by the C++11
+ // case, where the moves could alter a new element belonging
+ // to the existing vector. This is an issue only for callers
+ // taking the element by lvalue ref (see last bullet of C++11
+ // [res.on.arguments]).
+
+ // If this throws, the existing elements are unchanged.
#if __cplusplus >= 201103L
- std::forward<_Args>(__args)...);
+ _Alloc_traits::construct(this->_M_impl,
+ std::__to_address(__new_start + __elems_before),
+ std::forward<_Args>(__args)...);
#else
- __x);
+ _Alloc_traits::construct(this->_M_impl,
+ __new_start + __elems_before,
+ __x);
#endif
- __new_finish = pointer();
#if __cplusplus >= 201103L
- if _GLIBCXX17_CONSTEXPR (_S_use_relocate())
- {
- __new_finish = _S_relocate(__old_start, __position.base(),
- __new_start, _M_get_Tp_allocator());
+ if _GLIBCXX17_CONSTEXPR (_S_use_relocate())
+ {
+ // Relocation cannot throw.
+ __new_finish = _S_relocate(__old_start, __position.base(),
+ __new_start, _M_get_Tp_allocator());
+ ++__new_finish;
+ __new_finish = _S_relocate(__position.base(), __old_finish,
+ __new_finish, _M_get_Tp_allocator());
+ }
+ else
+#endif
+ {
+ // RAII type to destroy initialized elements.
+ struct _Guard_elts
+ {
+ pointer _M_first, _M_last; // Elements to destroy
+ _Tp_alloc_type& _M_alloc;
- ++__new_finish;
+ _GLIBCXX20_CONSTEXPR
+ _Guard_elts(pointer __elt, _Tp_alloc_type& __a)
+ : _M_first(__elt), _M_last(__elt + 1), _M_alloc(__a)
+ { }
- __new_finish = _S_relocate(__position.base(), __old_finish,
- __new_finish, _M_get_Tp_allocator());
- }
- else
-#endif
- {
- __new_finish
- = std::__uninitialized_move_if_noexcept_a
- (__old_start, __position.base(),
- __new_start, _M_get_Tp_allocator());
+ _GLIBCXX20_CONSTEXPR
+ ~_Guard_elts()
+ { std::_Destroy(_M_first, _M_last, _M_alloc); }
- ++__new_finish;
+ private:
+ _Guard_elts(const _Guard_elts&);
+ };
- __new_finish
- = std::__uninitialized_move_if_noexcept_a
- (__position.base(), __old_finish,
- __new_finish, _M_get_Tp_allocator());
- }
- }
- __catch(...)
- {
- if (!__new_finish)
- _Alloc_traits::destroy(this->_M_impl,
- __new_start + __elems_before);
- else
- std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator());
- _M_deallocate(__new_start, __len);
- __throw_exception_again;
+ // Guard the new element so it will be destroyed if anything throws.
+ _Guard_elts __guard_elts(__new_start + __elems_before, _M_impl);
+
+ __new_finish = std::__uninitialized_move_if_noexcept_a(
+ __old_start, __position.base(),
+ __new_start, _M_get_Tp_allocator());
+
+ ++__new_finish;
+ // Guard everything before the new element too.
+ __guard_elts._M_first = __new_start;
+
+ __new_finish = std::__uninitialized_move_if_noexcept_a(
+ __position.base(), __old_finish,
+ __new_finish, _M_get_Tp_allocator());
+
+ // New storage has been fully initialized, destroy the old elements.
+ __guard_elts._M_first = __old_start;
+ __guard_elts._M_last = __old_finish;
}
-#if __cplusplus >= 201103L
- if _GLIBCXX17_CONSTEXPR (!_S_use_relocate())
-#endif
- std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator());
- _GLIBCXX_ASAN_ANNOTATE_REINIT;
- _M_deallocate(__old_start,
- this->_M_impl._M_end_of_storage - __old_start);
+ __guard._M_storage = __old_start;
+ __guard._M_len = this->_M_impl._M_end_of_storage - __old_start;
+
this->_M_impl._M_start = __new_start;
this->_M_impl._M_finish = __new_finish;
this->_M_impl._M_end_of_storage = __new_start + __len;