[libcxx-commits] [libcxx] [libc++][vector] Make constructor vector(count, value, allocator) exception-safe (PR #82033)

Mateusz Zych via libcxx-commits libcxx-commits at lists.llvm.org
Fri Feb 16 11:49:46 PST 2024


https://github.com/mtezych created https://github.com/llvm/llvm-project/pull/82033

The constructor `std::vector(count, value, allocator)` was missing an exception guard,
responsible for destroying successfully created elements, in case an exception was thrown:
- https://godbolt.org/z/MeK37n8fb

Since all constructors filling `std::vector<>` with elements of the same value:
 - `vector(count)`
 - `vector(count, allocator)`
 - `vector(count, value)`
 - `vector(count, value, allocator)`

have nearly identical implementation, their definitions should be physically close to each other.

In order to achieve that goal, the constructor `std::vector(count, value, allocator)` is now defined
outside of the `std::vector<>` class template and has sightly different `enable_if<>` expression,
matching to those used in the constructors taking two iterators:
 - `vector(iterator first, iterator last)`
 - `vector(iterator first, iterator last, allocator)`

>From c418611b3fc2dc727eb3b3f82aa1b513b61d1136 Mon Sep 17 00:00:00 2001
From: Mateusz Zych <mte.zych at gmail.com>
Date: Fri, 16 Feb 2024 21:29:53 +0300
Subject: [PATCH] [libc++][vector] Make constructor vector(count, value,
 allocator) exception-safe

---
 libcxx/include/vector | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/libcxx/include/vector b/libcxx/include/vector
index ce7df7a9f04207..62d36d9318bd69 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -429,15 +429,9 @@ public:
 #endif
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI vector(size_type __n, const value_type& __x);
 
-  template <class = __enable_if_t<__is_allocator<_Allocator>::value> >
+  template <__enable_if_t<__is_allocator<_Allocator>::value, int> = 0>
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI
-  vector(size_type __n, const value_type& __x, const allocator_type& __a)
-      : __end_cap_(nullptr, __a) {
-    if (__n > 0) {
-      __vallocate(__n);
-      __construct_at_end(__n, __x);
-    }
-  }
+  vector(size_type __n, const value_type& __x, const allocator_type& __a);
 
   template <class _InputIterator,
             __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value &&
@@ -1165,6 +1159,19 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 vector<_Tp, _Allocator>::vector(size_type __n, con
   __guard.__complete();
 }
 
+template <class _Tp, class _Allocator>
+template <__enable_if_t<__is_allocator<_Allocator>::value, int>>
+_LIBCPP_CONSTEXPR_SINCE_CXX20
+vector<_Tp, _Allocator>::vector(size_type __n, const value_type& __x, const allocator_type& __a)
+    : __end_cap_(nullptr, __a) {
+  auto __guard = std::__make_exception_guard(__destroy_vector(*this));
+  if (__n > 0) {
+    __vallocate(__n);
+    __construct_at_end(__n, __x);
+  }
+  __guard.__complete();
+}
+
 template <class _Tp, class _Allocator>
 template <class _InputIterator,
           __enable_if_t<__has_exactly_input_iterator_category<_InputIterator>::value &&



More information about the libcxx-commits mailing list