Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc++] Add container_traits (prework for std::flat_map) #109578

Merged
merged 3 commits into from
Oct 12, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,7 @@ set(files
__type_traits/common_type.h
__type_traits/conditional.h
__type_traits/conjunction.h
__type_traits/container_traits.h
__type_traits/copy_cv.h
__type_traits/copy_cvref.h
__type_traits/datasizeof.h
Expand Down
36 changes: 36 additions & 0 deletions libcxx/include/__type_traits/container_traits.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___TYPE_TRAITS_CONTAINER_TRAITS_H
#define _LIBCPP___TYPE_TRAITS_CONTAINER_TRAITS_H

#include <__config>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

huixie90 marked this conversation as resolved.
Show resolved Hide resolved
// __container_traits is a general purpose struct contains traits of containers' different operations.
// It currently only has one trait: `__emplacement_has_strong_exception_safety_guarantee`, but it's
// intended to be extended in the future.
// If a container does not support an operation. For example, `std::array` does not support `insert`
// or `emplace`, the trait of that operation will return false.
huixie90 marked this conversation as resolved.
Show resolved Hide resolved
template <class _Container>
struct __container_traits {
huixie90 marked this conversation as resolved.
Show resolved Hide resolved
// A trait that tells whether a single element insertion/emplacement via member function
// `insert(...)` or `emplace(...)` has strong exception guarantee, that is, if the function
// exits via an exception, the original container is unaffected
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee = false;
};

_LIBCPP_END_NAMESPACE_STD

#endif // _LIBCPP___TYPE_TRAITS_CONTAINER_TRAITS_H
13 changes: 13 additions & 0 deletions libcxx/include/deque
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ template <class T, class Allocator, class Predicate>
#include <__ranges/size.h>
#include <__split_buffer>
#include <__type_traits/conditional.h>
#include <__type_traits/container_traits.h>
#include <__type_traits/disjunction.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_allocator.h>
#include <__type_traits/is_convertible.h>
Expand Down Expand Up @@ -2609,6 +2611,17 @@ inline constexpr bool __format::__enable_insertable<std::deque<wchar_t>> = true;

#endif // _LIBCPP_STD_VER >= 20

template <class _Tp, class _Allocator>
struct __container_traits<deque<_Tp, _Allocator> > {
// http://eel.is/c++draft/deque.modifiers#3
// If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move
// assignment operator of T, there are no effects. If an exception is thrown while inserting a single element at
// either end, there are no effects. Otherwise, if an exception is thrown by the move constructor of a
// non-Cpp17CopyInsertable T, the effects are unspecified.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee =
_Or<is_nothrow_move_constructible<_Tp>, __is_cpp17_copy_insertable<_Allocator> >::value;
};

_LIBCPP_END_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 17
Expand Down
12 changes: 12 additions & 0 deletions libcxx/include/forward_list
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ template <class T, class Allocator, class Predicate>
#include <__ranges/container_compatible_range.h>
#include <__ranges/from_range.h>
#include <__type_traits/conditional.h>
#include <__type_traits/container_traits.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_allocator.h>
#include <__type_traits/is_const.h>
Expand Down Expand Up @@ -1544,6 +1545,17 @@ erase(forward_list<_Tp, _Allocator>& __c, const _Up& __v) {
}
#endif

template <class _Tp, class _Allocator>
struct __container_traits<forward_list<_Tp, _Allocator> > {
// http://eel.is/c++draft/container.reqmts
// Unless otherwise specified (see [associative.reqmts.except], [unord.req.except], [deque.modifiers],
// [inplace.vector.modifiers], and [vector.modifiers]) all container types defined in this Clause meet the following
// additional requirements:
// - If an exception is thrown by an insert() or emplace() function while inserting a single element, that
// function has no effects.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee = true;
};

_LIBCPP_END_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 17
Expand Down
12 changes: 12 additions & 0 deletions libcxx/include/list
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ template <class T, class Allocator, class Predicate>
#include <__ranges/container_compatible_range.h>
#include <__ranges/from_range.h>
#include <__type_traits/conditional.h>
#include <__type_traits/container_traits.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_allocator.h>
#include <__type_traits/is_nothrow_assignable.h>
Expand Down Expand Up @@ -1715,6 +1716,17 @@ inline constexpr bool __format::__enable_insertable<std::list<wchar_t>> = true;

#endif // _LIBCPP_STD_VER >= 20

template <class _Tp, class _Allocator>
struct __container_traits<list<_Tp, _Allocator> > {
// http://eel.is/c++draft/container.reqmts
// Unless otherwise specified (see [associative.reqmts.except], [unord.req.except], [deque.modifiers],
// [inplace.vector.modifiers], and [vector.modifiers]) all container types defined in this Clause meet the following
// additional requirements:
// - If an exception is thrown by an insert() or emplace() function while inserting a single element, that
// function has no effects.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee = true;
};

_LIBCPP_END_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 17
Expand Down
17 changes: 17 additions & 0 deletions libcxx/include/map
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,7 @@ erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred); // C++20
#include <__ranges/container_compatible_range.h>
#include <__ranges/from_range.h>
#include <__tree>
#include <__type_traits/container_traits.h>
#include <__type_traits/is_allocator.h>
#include <__type_traits/remove_const.h>
#include <__type_traits/type_identity.h>
Expand Down Expand Up @@ -1644,6 +1645,14 @@ erase_if(map<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) {
}
#endif

template <class _Key, class _Tp, class _Compare, class _Allocator>
struct __container_traits<map<_Key, _Tp, _Compare, _Allocator> > {
// http://eel.is/c++draft/associative.reqmts.except#2
// For associative containers, if an exception is thrown by any operation from within
// an insert or emplace function inserting a single element, the insertion has no effect.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee = true;
};

template <class _Key, class _Tp, class _Compare = less<_Key>, class _Allocator = allocator<pair<const _Key, _Tp> > >
class _LIBCPP_TEMPLATE_VIS multimap {
public:
Expand Down Expand Up @@ -2158,6 +2167,14 @@ erase_if(multimap<_Key, _Tp, _Compare, _Allocator>& __c, _Predicate __pred) {
}
#endif

template <class _Key, class _Tp, class _Compare, class _Allocator>
struct __container_traits<multimap<_Key, _Tp, _Compare, _Allocator> > {
// http://eel.is/c++draft/associative.reqmts.except#2
// For associative containers, if an exception is thrown by any operation from within
// an insert or emplace function inserting a single element, the insertion has no effect.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee = true;
};

_LIBCPP_END_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 17
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ module std_core [system] {
module common_type { header "__type_traits/common_type.h" }
module conditional { header "__type_traits/conditional.h" }
module conjunction { header "__type_traits/conjunction.h" }
module container_traits { header "__type_traits/container_traits.h" }
module copy_cv { header "__type_traits/copy_cv.h" }
module copy_cvref { header "__type_traits/copy_cvref.h" }
module datasizeof { header "__type_traits/datasizeof.h" }
Expand Down
17 changes: 17 additions & 0 deletions libcxx/include/set
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@ erase_if(multiset<Key, Compare, Allocator>& c, Predicate pred); // C++20
#include <__ranges/container_compatible_range.h>
#include <__ranges/from_range.h>
#include <__tree>
#include <__type_traits/container_traits.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_allocator.h>
#include <__type_traits/is_nothrow_assignable.h>
Expand Down Expand Up @@ -1022,6 +1023,14 @@ erase_if(set<_Key, _Compare, _Allocator>& __c, _Predicate __pred) {
}
#endif

template <class _Key, class _Compare, class _Allocator>
struct __container_traits<set<_Key, _Compare, _Allocator> > {
// http://eel.is/c++draft/associative.reqmts.except#2
// For associative containers, if an exception is thrown by any operation from within
// an insert or emplace function inserting a single element, the insertion has no effect.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee = true;
};

template <class _Key, class _Compare = less<_Key>, class _Allocator = allocator<_Key> >
class _LIBCPP_TEMPLATE_VIS multiset {
public:
Expand Down Expand Up @@ -1481,6 +1490,14 @@ erase_if(multiset<_Key, _Compare, _Allocator>& __c, _Predicate __pred) {
}
#endif

template <class _Key, class _Compare, class _Allocator>
struct __container_traits<multiset<_Key, _Compare, _Allocator> > {
// http://eel.is/c++draft/associative.reqmts.except#2
// For associative containers, if an exception is thrown by any operation from within
// an insert or emplace function inserting a single element, the insertion has no effect.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee = true;
};

_LIBCPP_END_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 17
Expand Down
22 changes: 22 additions & 0 deletions libcxx/include/unordered_map
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,9 @@ template <class Key, class T, class Hash, class Pred, class Alloc>
#include <__ranges/concepts.h>
#include <__ranges/container_compatible_range.h>
#include <__ranges/from_range.h>
#include <__type_traits/container_traits.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/invoke.h>
#include <__type_traits/is_allocator.h>
huixie90 marked this conversation as resolved.
Show resolved Hide resolved
#include <__type_traits/is_integral.h>
#include <__type_traits/remove_const.h>
Expand Down Expand Up @@ -1830,6 +1832,16 @@ inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const unordered_map<_Key, _Tp, _Has

#endif

template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
struct __container_traits<unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc> > {
// http://eel.is/c++draft/unord.req.except#2
// For unordered associative containers, if an exception is thrown by any operation
// other than the container's hash function from within an insert or emplace function
// inserting a single element, the insertion has no effect.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee =
__nothrow_invokable<_Hash, const _Key&>::value;
};

template <class _Key,
class _Tp,
class _Hash = hash<_Key>,
Expand Down Expand Up @@ -2520,6 +2532,16 @@ inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const unordered_multimap<_Key, _Tp,

#endif

template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
struct __container_traits<unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc> > {
// http://eel.is/c++draft/unord.req.except#2
// For unordered associative containers, if an exception is thrown by any operation
// other than the container's hash function from within an insert or emplace function
// inserting a single element, the insertion has no effect.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee =
__nothrow_invokable<_Hash, const _Key&>::value;
};

_LIBCPP_END_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 17
Expand Down
22 changes: 22 additions & 0 deletions libcxx/include/unordered_set
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,9 @@ template <class Value, class Hash, class Pred, class Alloc>
#include <__ranges/concepts.h>
#include <__ranges/container_compatible_range.h>
#include <__ranges/from_range.h>
#include <__type_traits/container_traits.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/invoke.h>
#include <__type_traits/is_allocator.h>
#include <__type_traits/is_integral.h>
#include <__type_traits/is_nothrow_assignable.h>
Expand Down Expand Up @@ -1183,6 +1185,16 @@ inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const unordered_set<_Value, _Hash,

#endif

template <class _Value, class _Hash, class _Pred, class _Alloc>
struct __container_traits<unordered_set<_Value, _Hash, _Pred, _Alloc> > {
// http://eel.is/c++draft/unord.req.except#2
// For unordered associative containers, if an exception is thrown by any operation
// other than the container's hash function from within an insert or emplace function
// inserting a single element, the insertion has no effect.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee =
__nothrow_invokable<_Hash, const _Value&>::value;
};

template <class _Value, class _Hash = hash<_Value>, class _Pred = equal_to<_Value>, class _Alloc = allocator<_Value> >
class _LIBCPP_TEMPLATE_VIS unordered_multiset {
public:
Expand Down Expand Up @@ -1793,6 +1805,16 @@ inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const unordered_multiset<_Value, _H

#endif

template <class _Value, class _Hash, class _Pred, class _Alloc>
struct __container_traits<unordered_multiset<_Value, _Hash, _Pred, _Alloc> > {
// http://eel.is/c++draft/unord.req.except#2
// For unordered associative containers, if an exception is thrown by any operation
// other than the container's hash function from within an insert or emplace function
// inserting a single element, the insertion has no effect.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee =
__nothrow_invokable<_Hash, const _Value&>::value;
};

_LIBCPP_END_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 17
Expand Down
14 changes: 14 additions & 0 deletions libcxx/include/vector
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,8 @@ template<class T, class charT> requires is-vector-bool-reference<T> // Since C++
#include <__ranges/size.h>
#include <__split_buffer>
#include <__type_traits/conditional.h>
#include <__type_traits/container_traits.h>
#include <__type_traits/disjunction.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_allocator.h>
#include <__type_traits/is_constructible.h>
Expand Down Expand Up @@ -3005,6 +3007,18 @@ public:
};
#endif // _LIBCPP_STD_VER >= 23

template <class _Tp, class _Allocator>
struct __container_traits<vector<_Tp, _Allocator> > {
// http://eel.is/c++draft/vector.modifiers#2
// If an exception is thrown other than by the copy constructor, move constructor, assignment operator, or move
// assignment operator of T or by any InputIterator operation, there are no effects. If an exception is thrown while
// inserting a single element at the end and T is Cpp17CopyInsertable or is_nothrow_move_constructible_v<T> is true,
// there are no effects. Otherwise, if an exception is thrown by the move constructor of a non-Cpp17CopyInsertable T,
// the effects are unspecified.
static _LIBCPP_CONSTEXPR const bool __emplacement_has_strong_exception_safety_guarantee =
_Or<is_nothrow_move_constructible<_Tp>, __is_cpp17_copy_insertable<_Allocator> >::value;
};

_LIBCPP_END_NAMESPACE_STD

#if _LIBCPP_STD_VER >= 17
Expand Down
Loading
Loading