Skip to content

Commit 3320751

Browse files
committed
[libc++] Add containter_traits (prework for std::flat_map)
1 parent 2f1e04f commit 3320751

File tree

12 files changed

+328
-0
lines changed

12 files changed

+328
-0
lines changed

libcxx/include/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,7 @@ set(files
748748
__type_traits/common_type.h
749749
__type_traits/conditional.h
750750
__type_traits/conjunction.h
751+
__type_traits/container_traits.h
751752
__type_traits/copy_cv.h
752753
__type_traits/copy_cvref.h
753754
__type_traits/datasizeof.h
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
#ifndef _LIBCPP___TYPE_TRAITS_CONTAINER_TRAITS_H
10+
#define _LIBCPP___TYPE_TRAITS_CONTAINER_TRAITS_H
11+
12+
#include <__config>
13+
#include <__type_traits/integral_constant.h>
14+
15+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
16+
# pragma GCC system_header
17+
#endif
18+
19+
_LIBCPP_BEGIN_NAMESPACE_STD
20+
21+
template <class _Tp>
22+
struct __container_traits {
23+
using __emplacement_has_strong_exception_safety_guarantee = false_type;
24+
};
25+
26+
_LIBCPP_END_NAMESPACE_STD
27+
28+
#endif // _LIBCPP___TYPE_TRAITS_CONTAINER_TRAITS_H

libcxx/include/deque

+14
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ template <class T, class Allocator, class Predicate>
220220
#include <__ranges/size.h>
221221
#include <__split_buffer>
222222
#include <__type_traits/conditional.h>
223+
#include <__type_traits/container_traits.h>
224+
#include <__type_traits/disjunction.h>
223225
#include <__type_traits/enable_if.h>
224226
#include <__type_traits/is_allocator.h>
225227
#include <__type_traits/is_convertible.h>
@@ -2609,6 +2611,18 @@ inline constexpr bool __format::__enable_insertable<std::deque<wchar_t>> = true;
26092611

26102612
#endif // _LIBCPP_STD_VER >= 20
26112613

2614+
template <class _Tp, class _Allocator>
2615+
struct __container_traits<deque<_Tp, _Allocator> > {
2616+
// http://eel.is/c++draft/deque.modifiers#3
2617+
// If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move
2618+
// assignment operator of T, there are no effects. If an exception is thrown while inserting a single element at
2619+
// either end, there are no effects. Otherwise, if an exception is thrown by the move constructor of a
2620+
// non-Cpp17CopyInsertable T, the effects are unspecified.
2621+
using __emplacement_has_strong_exception_safety_guarantee =
2622+
_Or<is_nothrow_move_constructible<_Tp>,
2623+
__is_cpp17_copy_insertable<typename deque<_Tp, _Allocator>::allocator_type> >;
2624+
};
2625+
26122626
_LIBCPP_END_NAMESPACE_STD
26132627

26142628
#if _LIBCPP_STD_VER >= 17

libcxx/include/forward_list

+12
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ template <class T, class Allocator, class Predicate>
218218
#include <__ranges/container_compatible_range.h>
219219
#include <__ranges/from_range.h>
220220
#include <__type_traits/conditional.h>
221+
#include <__type_traits/container_traits.h>
221222
#include <__type_traits/enable_if.h>
222223
#include <__type_traits/is_allocator.h>
223224
#include <__type_traits/is_const.h>
@@ -1544,6 +1545,17 @@ erase(forward_list<_Tp, _Allocator>& __c, const _Up& __v) {
15441545
}
15451546
#endif
15461547

1548+
template <class _Tp, class _Allocator>
1549+
struct __container_traits<forward_list<_Tp, _Allocator> > {
1550+
// http://eel.is/c++draft/container.reqmts
1551+
// 66 Unless otherwise specified (see [associative.reqmts.except], [unord.req.except], [deque.modifiers],
1552+
// [inplace.vector.modifiers], and [vector.modifiers]) all container types defined in this Clause meet the following
1553+
// additional requirements:
1554+
// - (66.1) If an exception is thrown by an insert() or emplace() function while inserting a single element, that
1555+
// function has no effects.
1556+
using __emplacement_has_strong_exception_safety_guarantee = true_type;
1557+
};
1558+
15471559
_LIBCPP_END_NAMESPACE_STD
15481560

15491561
#if _LIBCPP_STD_VER >= 17

libcxx/include/list

+12
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ template <class T, class Allocator, class Predicate>
225225
#include <__ranges/container_compatible_range.h>
226226
#include <__ranges/from_range.h>
227227
#include <__type_traits/conditional.h>
228+
#include <__type_traits/container_traits.h>
228229
#include <__type_traits/enable_if.h>
229230
#include <__type_traits/is_allocator.h>
230231
#include <__type_traits/is_nothrow_assignable.h>
@@ -1715,6 +1716,17 @@ inline constexpr bool __format::__enable_insertable<std::list<wchar_t>> = true;
17151716

17161717
#endif // _LIBCPP_STD_VER >= 20
17171718

1719+
template <class _Tp, class _Allocator>
1720+
struct __container_traits<list<_Tp, _Allocator> > {
1721+
// http://eel.is/c++draft/container.reqmts
1722+
// 66 Unless otherwise specified (see [associative.reqmts.except], [unord.req.except], [deque.modifiers],
1723+
// [inplace.vector.modifiers], and [vector.modifiers]) all container types defined in this Clause meet the following
1724+
// additional requirements:
1725+
// - (66.1) If an exception is thrown by an insert() or emplace() function while inserting a single element, that
1726+
// function has no effects.
1727+
using __emplacement_has_strong_exception_safety_guarantee = true_type;
1728+
};
1729+
17181730
_LIBCPP_END_NAMESPACE_STD
17191731

17201732
#if _LIBCPP_STD_VER >= 17

libcxx/include/map

+17
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred); // C++20
594594
#include <__ranges/container_compatible_range.h>
595595
#include <__ranges/from_range.h>
596596
#include <__tree>
597+
#include <__type_traits/container_traits.h>
597598
#include <__type_traits/is_allocator.h>
598599
#include <__type_traits/remove_const.h>
599600
#include <__type_traits/type_identity.h>
@@ -1644,6 +1645,14 @@ erase_if(map<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) {
16441645
}
16451646
#endif
16461647

1648+
template <class _Key, class _Tp, class _Compare, class _Allocator>
1649+
struct __container_traits<map<_Key, _Tp, _Compare, _Allocator> > {
1650+
// http://eel.is/c++draft/associative.reqmts.except#2
1651+
// For associative containers, if an exception is thrown by any operation from within
1652+
// an insert or emplace function inserting a single element, the insertion has no effect.
1653+
using __emplacement_has_strong_exception_safety_guarantee = true_type;
1654+
};
1655+
16471656
template <class _Key, class _Tp, class _Compare = less<_Key>, class _Allocator = allocator<pair<const _Key, _Tp> > >
16481657
class _LIBCPP_TEMPLATE_VIS multimap {
16491658
public:
@@ -2158,6 +2167,14 @@ erase_if(multimap<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) {
21582167
}
21592168
#endif
21602169

2170+
template <class _Key, class _Tp, class _Compare, class _Allocator>
2171+
struct __container_traits<multimap<_Key, _Tp, _Compare, _Allocator> > {
2172+
// http://eel.is/c++draft/associative.reqmts.except#2
2173+
// For associative containers, if an exception is thrown by any operation from within
2174+
// an insert or emplace function inserting a single element, the insertion has no effect.
2175+
using __emplacement_has_strong_exception_safety_guarantee = true_type;
2176+
};
2177+
21612178
_LIBCPP_END_NAMESPACE_STD
21622179

21632180
#if _LIBCPP_STD_VER >= 17

libcxx/include/module.modulemap

+1
Original file line numberDiff line numberDiff line change
@@ -1864,6 +1864,7 @@ module std_private_type_traits_common_type [system
18641864
}
18651865
module std_private_type_traits_conditional [system] { header "__type_traits/conditional.h" }
18661866
module std_private_type_traits_conjunction [system] { header "__type_traits/conjunction.h" }
1867+
module std_private_type_traits_container_traits [system] { header "__type_traits/container_traits.h" }
18671868
module std_private_type_traits_copy_cv [system] { header "__type_traits/copy_cv.h" }
18681869
module std_private_type_traits_copy_cvref [system] { header "__type_traits/copy_cvref.h" }
18691870
module std_private_type_traits_datasizeof [system] { header "__type_traits/datasizeof.h" }

libcxx/include/set

+17
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred); // C++20
531531
#include <__ranges/container_compatible_range.h>
532532
#include <__ranges/from_range.h>
533533
#include <__tree>
534+
#include <__type_traits/container_traits.h>
534535
#include <__type_traits/enable_if.h>
535536
#include <__type_traits/is_allocator.h>
536537
#include <__type_traits/is_nothrow_assignable.h>
@@ -1022,6 +1023,14 @@ erase_if(set<_Key, _Compare, _Allocator>& __c, _Predicate __pred) {
10221023
}
10231024
#endif
10241025

1026+
template <class _Key, class _Compare, class _Allocator>
1027+
struct __container_traits<set<_Key, _Compare, _Allocator> > {
1028+
// http://eel.is/c++draft/associative.reqmts.except#2
1029+
// For associative containers, if an exception is thrown by any operation from within
1030+
// an insert or emplace function inserting a single element, the insertion has no effect.
1031+
using __emplacement_has_strong_exception_safety_guarantee = true_type;
1032+
};
1033+
10251034
template <class _Key, class _Compare = less<_Key>, class _Allocator = allocator<_Key> >
10261035
class _LIBCPP_TEMPLATE_VIS multiset {
10271036
public:
@@ -1481,6 +1490,14 @@ erase_if(multiset<_Key, _Compare, _Allocator>& __c, _Predicate __pred) {
14811490
}
14821491
#endif
14831492

1493+
template <class _Key, class _Compare, class _Allocator>
1494+
struct __container_traits<multiset<_Key, _Compare, _Allocator> > {
1495+
// http://eel.is/c++draft/associative.reqmts.except#2
1496+
// For associative containers, if an exception is thrown by any operation from within
1497+
// an insert or emplace function inserting a single element, the insertion has no effect.
1498+
using __emplacement_has_strong_exception_safety_guarantee = true_type;
1499+
};
1500+
14841501
_LIBCPP_END_NAMESPACE_STD
14851502

14861503
#if _LIBCPP_STD_VER >= 17

libcxx/include/unordered_map

+19
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ template <class Key, class T, class Hash, class Pred, class Alloc>
604604
#include <__ranges/concepts.h>
605605
#include <__ranges/container_compatible_range.h>
606606
#include <__ranges/from_range.h>
607+
#include <__type_traits/container_traits.h>
607608
#include <__type_traits/enable_if.h>
608609
#include <__type_traits/is_allocator.h>
609610
#include <__type_traits/is_integral.h>
@@ -1830,6 +1831,15 @@ inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const unordered_map<_Key, _Tp, _Has
18301831

18311832
#endif
18321833

1834+
template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
1835+
struct __container_traits<unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> > {
1836+
// http://eel.is/c++draft/unord.req.except#2
1837+
// For unordered associative containers, if an exception is thrown by any operation
1838+
// other than the container's hash function from within an insert or emplace function
1839+
// inserting a single element, the insertion has no effect.
1840+
using __emplacement_has_strong_exception_safety_guarantee = __nothrow_invokable<_Hash, const _Key&>;
1841+
};
1842+
18331843
template <class _Key,
18341844
class _Tp,
18351845
class _Hash = hash<_Key>,
@@ -2520,6 +2530,15 @@ inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const unordered_multimap<_Key, _Tp,
25202530

25212531
#endif
25222532

2533+
template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
2534+
struct __container_traits<unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc> > {
2535+
// http://eel.is/c++draft/unord.req.except#2
2536+
// For unordered associative containers, if an exception is thrown by any operation
2537+
// other than the container's hash function from within an insert or emplace function
2538+
// inserting a single element, the insertion has no effect.
2539+
using __emplacement_has_strong_exception_safety_guarantee = __nothrow_invokable<_Hash, const _Key&>;
2540+
};
2541+
25232542
_LIBCPP_END_NAMESPACE_STD
25242543

25252544
#if _LIBCPP_STD_VER >= 17

libcxx/include/unordered_set

+19
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ template <class Value, class Hash, class Pred, class Alloc>
550550
#include <__ranges/concepts.h>
551551
#include <__ranges/container_compatible_range.h>
552552
#include <__ranges/from_range.h>
553+
#include <__type_traits/container_traits.h>
553554
#include <__type_traits/enable_if.h>
554555
#include <__type_traits/is_allocator.h>
555556
#include <__type_traits/is_integral.h>
@@ -1183,6 +1184,15 @@ inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const unordered_set<_Value, _Hash,
11831184

11841185
#endif
11851186

1187+
template <class _Value, class _Hash, class _Pred, class _Alloc>
1188+
struct __container_traits<unordered_set<_Value, _Hash, _Pred, _Alloc> > {
1189+
// http://eel.is/c++draft/unord.req.except#2
1190+
// For unordered associative containers, if an exception is thrown by any operation
1191+
// other than the container's hash function from within an insert or emplace function
1192+
// inserting a single element, the insertion has no effect.
1193+
using __emplacement_has_strong_exception_safety_guarantee = __nothrow_invokable<_Hash, const _Value&>;
1194+
};
1195+
11861196
template <class _Value, class _Hash = hash<_Value>, class _Pred = equal_to<_Value>, class _Alloc = allocator<_Value> >
11871197
class _LIBCPP_TEMPLATE_VIS unordered_multiset {
11881198
public:
@@ -1793,6 +1803,15 @@ inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const unordered_multiset<_Value, _H
17931803

17941804
#endif
17951805

1806+
template <class _Value, class _Hash, class _Pred, class _Alloc>
1807+
struct __container_traits<unordered_multiset<_Value, _Hash, _Pred, _Alloc> > {
1808+
// http://eel.is/c++draft/unord.req.except#2
1809+
// For unordered associative containers, if an exception is thrown by any operation
1810+
// other than the container's hash function from within an insert or emplace function
1811+
// inserting a single element, the insertion has no effect.
1812+
using __emplacement_has_strong_exception_safety_guarantee = __nothrow_invokable<_Hash, const _Value&>;
1813+
};
1814+
17961815
_LIBCPP_END_NAMESPACE_STD
17971816

17981817
#if _LIBCPP_STD_VER >= 17

libcxx/include/vector

+15
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,8 @@ template<class T, class charT> requires is-vector-bool-reference<T> // Since C++
356356
#include <__ranges/size.h>
357357
#include <__split_buffer>
358358
#include <__type_traits/conditional.h>
359+
#include <__type_traits/container_traits.h>
360+
#include <__type_traits/disjunction.h>
359361
#include <__type_traits/enable_if.h>
360362
#include <__type_traits/is_allocator.h>
361363
#include <__type_traits/is_constructible.h>
@@ -3005,6 +3007,19 @@ public:
30053007
};
30063008
#endif // _LIBCPP_STD_VER >= 23
30073009

3010+
template <class _Tp, class _Allocator>
3011+
struct __container_traits<vector<_Tp, _Allocator> > {
3012+
// http://eel.is/c++draft/vector.modifiers#2
3013+
// If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move
3014+
// assignment operator of T or by any InputIterator operation, there are no effects. If an exception is thrown while
3015+
// inserting a single element at the end and T is Cpp17CopyInsertable or is_nothrow_move_constructible_v<T> is true,
3016+
// there are no effects. Otherwise, if an exception is thrown by the move constructor of a non-Cpp17CopyInsertable T,
3017+
// the effects are unspecified.
3018+
using __emplacement_has_strong_exception_safety_guarantee =
3019+
_Or<is_nothrow_move_constructible<_Tp>,
3020+
__is_cpp17_copy_insertable<typename vector<_Tp, _Allocator>::allocator_type> >;
3021+
};
3022+
30083023
_LIBCPP_END_NAMESPACE_STD
30093024

30103025
#if _LIBCPP_STD_VER >= 17

0 commit comments

Comments
 (0)