Skip to content

Commit 692c5cd

Browse files
authored
[libc++] Do not call reserve in flat containers if underlying container is user defined (#140379)
This is brought up in the LWG reflector. We currently call `reserve` if the underlying container has one. But the spec does not specify what `reserve` should do for Sequence Container. So in theory if the underlying container is user defined type and it can have a function called `reserve` which does something completely different. The fix is to just call `reserve` for STL containers if it has one
1 parent 90a52f4 commit 692c5cd

File tree

18 files changed

+70
-6
lines changed

18 files changed

+70
-6
lines changed

libcxx/include/__flat_map/flat_map.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,11 +1012,11 @@ class flat_map {
10121012
}
10131013

10141014
_LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) {
1015-
if constexpr (requires { __containers_.keys.reserve(__size); }) {
1015+
if constexpr (__container_traits<_KeyContainer>::__reservable) {
10161016
__containers_.keys.reserve(__size);
10171017
}
10181018

1019-
if constexpr (requires { __containers_.values.reserve(__size); }) {
1019+
if constexpr (__container_traits<_MappedContainer>::__reservable) {
10201020
__containers_.values.reserve(__size);
10211021
}
10221022
}

libcxx/include/__flat_map/flat_multimap.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -827,11 +827,11 @@ class flat_multimap {
827827
}
828828

829829
_LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) {
830-
if constexpr (requires { __containers_.keys.reserve(__size); }) {
830+
if constexpr (__container_traits<_KeyContainer>::__reservable) {
831831
__containers_.keys.reserve(__size);
832832
}
833833

834-
if constexpr (requires { __containers_.values.reserve(__size); }) {
834+
if constexpr (__container_traits<_MappedContainer>::__reservable) {
835835
__containers_.values.reserve(__size);
836836
}
837837
}

libcxx/include/__flat_set/flat_multiset.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ class flat_multiset {
667667
}
668668

669669
_LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) {
670-
if constexpr (requires { __keys_.reserve(__size); }) {
670+
if constexpr (__container_traits<_KeyContainer>::__reservable) {
671671
__keys_.reserve(__size);
672672
}
673673
}

libcxx/include/__flat_set/flat_set.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ class flat_set {
698698
}
699699

700700
_LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) {
701-
if constexpr (requires { __keys_.reserve(__size); }) {
701+
if constexpr (__container_traits<_KeyContainer>::__reservable) {
702702
__keys_.reserve(__size);
703703
}
704704
}

libcxx/include/__type_traits/container_traits.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ struct __container_traits {
3636
// `insert(...)` or `emplace(...)` has strong exception guarantee, that is, if the function
3737
// exits via an exception, the original container is unaffected
3838
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee = false;
39+
40+
// A trait that tells whether a container supports `reserve(n)` member function.
41+
static _LIBCPP_CONSTEXPR const bool __reservable = false;
3942
};
4043

4144
_LIBCPP_END_NAMESPACE_STD

libcxx/include/__vector/container_traits.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ struct __container_traits<vector<_Tp, _Allocator> > {
3232
// the effects are unspecified.
3333
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee =
3434
is_nothrow_move_constructible<_Tp>::value || __is_cpp17_copy_insertable_v<_Allocator>;
35+
36+
static _LIBCPP_CONSTEXPR const bool __reservable = true;
3537
};
3638

3739
_LIBCPP_END_NAMESPACE_STD

libcxx/include/deque

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,6 +2631,8 @@ struct __container_traits<deque<_Tp, _Allocator> > {
26312631
// non-Cpp17CopyInsertable T, the effects are unspecified.
26322632
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee =
26332633
is_nothrow_move_constructible<_Tp>::value || __is_cpp17_copy_insertable_v<_Allocator>;
2634+
2635+
static _LIBCPP_CONSTEXPR const bool __reservable = false;
26342636
};
26352637

26362638
_LIBCPP_END_NAMESPACE_STD

libcxx/include/forward_list

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,6 +1561,8 @@ struct __container_traits<forward_list<_Tp, _Allocator> > {
15611561
// - If an exception is thrown by an insert() or emplace() function while inserting a single element, that
15621562
// function has no effects.
15631563
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee = true;
1564+
1565+
static _LIBCPP_CONSTEXPR const bool __reservable = false;
15641566
};
15651567

15661568
_LIBCPP_END_NAMESPACE_STD

libcxx/include/list

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,6 +1718,8 @@ struct __container_traits<list<_Tp, _Allocator> > {
17181718
// - If an exception is thrown by an insert() or emplace() function while inserting a single element, that
17191719
// function has no effects.
17201720
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee = true;
1721+
1722+
static _LIBCPP_CONSTEXPR const bool __reservable = false;
17211723
};
17221724

17231725
_LIBCPP_END_NAMESPACE_STD

libcxx/include/map

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1548,6 +1548,8 @@ struct __container_traits<map<_Key, _Tp, _Compare, _Allocator> > {
15481548
// For associative containers, if an exception is thrown by any operation from within
15491549
// an insert or emplace function inserting a single element, the insertion has no effect.
15501550
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee = true;
1551+
1552+
static _LIBCPP_CONSTEXPR const bool __reservable = false;
15511553
};
15521554

15531555
template <class _Key, class _Tp, class _Compare, class _Allocator>
@@ -2071,6 +2073,8 @@ struct __container_traits<multimap<_Key, _Tp, _Compare, _Allocator> > {
20712073
// For associative containers, if an exception is thrown by any operation from within
20722074
// an insert or emplace function inserting a single element, the insertion has no effect.
20732075
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee = true;
2076+
2077+
static _LIBCPP_CONSTEXPR const bool __reservable = false;
20742078
};
20752079

20762080
_LIBCPP_END_NAMESPACE_STD

0 commit comments

Comments
 (0)