-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[libc++] Avoid constructing additional objects when using map::at #157866
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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_IS_GENERIC_TRANSPARENT_COMPARATOR_H | ||
#define _LIBCPP___TYPE_TRAITS_IS_GENERIC_TRANSPARENT_COMPARATOR_H | ||
|
||
#include <__config> | ||
|
||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
# pragma GCC system_header | ||
#endif | ||
|
||
_LIBCPP_BEGIN_NAMESPACE_STD | ||
|
||
// This traits returns true if the given _Comparator is known to accept any two types for compaison. This is separate | ||
// from `__is_transparent_v`, since that only enables overloads of specific functions, but doesn't give any semantic | ||
// guarantees. This trait guarantess that the comparator simply calls the appropriate comparison functions for any two | ||
// types. | ||
|
||
template <class _Comparator> | ||
inline const bool __is_generic_transparent_comparator_v = false; | ||
|
||
_LIBCPP_END_NAMESPACE_STD | ||
|
||
#endif // _LIBCPP___TYPE_TRAITS_IS_GENERIC_TRANSPARENT_COMPARATOR_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// 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_MAKE_TRANSPARENT_H | ||
#define _LIBCPP___TYPE_TRAITS_MAKE_TRANSPARENT_H | ||
|
||
#include <__config> | ||
#include <__type_traits/enable_if.h> | ||
#include <__type_traits/is_empty.h> | ||
#include <__type_traits/is_same.h> | ||
|
||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
# pragma GCC system_header | ||
#endif | ||
|
||
_LIBCPP_BEGIN_NAMESPACE_STD | ||
|
||
// __make_transparent tries to create a transparent comparator from its non-transparent counterpart, e.g. obtain | ||
// `less<>` from `less<T>`. This is useful in cases where conversions can be avoided (e.g. a string literal to a | ||
// std::string). | ||
|
||
template <class _Comparator> | ||
struct __make_transparent { | ||
philnik777 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
using type _LIBCPP_NODEBUG = _Comparator; | ||
}; | ||
|
||
template <class _Comparator> | ||
using __make_transparent_t _LIBCPP_NODEBUG = typename __make_transparent<_Comparator>::type; | ||
|
||
template <class _Comparator, __enable_if_t<is_same<_Comparator, __make_transparent_t<_Comparator> >::value, int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI _Comparator& __as_transparent(_Comparator& __comp) { | ||
return __comp; | ||
} | ||
|
||
template <class _Comparator, __enable_if_t<!is_same<_Comparator, __make_transparent_t<_Comparator> >::value, int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI __make_transparent_t<_Comparator> __as_transparent(_Comparator&) { | ||
philnik777 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
static_assert(is_empty<_Comparator>::value); | ||
return __make_transparent_t<_Comparator>(); | ||
} | ||
|
||
_LIBCPP_END_NAMESPACE_STD | ||
|
||
#endif // _LIBCPP___TYPE_TRAITS_MAKE_TRANSPARENT_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -600,7 +600,10 @@ erase_if(multimap<Key, T, Compare, Allocator>& c, Predicate pred); // C++20 | |
# include <__ranges/from_range.h> | ||
# include <__tree> | ||
# include <__type_traits/container_traits.h> | ||
# include <__type_traits/desugars_to.h> | ||
# include <__type_traits/is_allocator.h> | ||
# include <__type_traits/is_convertible.h> | ||
# include <__type_traits/make_transparent.h> | ||
# include <__type_traits/remove_const.h> | ||
# include <__type_traits/type_identity.h> | ||
# include <__utility/forward.h> | ||
|
@@ -666,6 +669,11 @@ public: | |
# endif | ||
}; | ||
|
||
template <class _Key, class _MapValueT, class _Compare> | ||
struct __make_transparent<__map_value_compare<_Key, _MapValueT, _Compare> > { | ||
using type _LIBCPP_NODEBUG = __map_value_compare<_Key, _MapValueT, __make_transparent_t<_Compare> >; | ||
}; | ||
|
||
# if _LIBCPP_STD_VER >= 14 | ||
template <class _MapValueT, class _Key, class _Compare> | ||
struct __lazy_synth_three_way_comparator<__map_value_compare<_Key, _MapValueT, _Compare>, _MapValueT, _MapValueT> { | ||
|
@@ -1048,6 +1056,24 @@ public: | |
_LIBCPP_HIDE_FROM_ABI mapped_type& operator[](key_type&& __k); | ||
# endif | ||
|
||
template <class _Arg, | ||
__enable_if_t<__is_transparently_comparable_v<_Compare, key_type, __remove_cvref_t<_Arg> >, int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI mapped_type& at(_Arg&& __arg) { | ||
auto [_, __child] = __tree_.__find_equal(__arg); | ||
if (__child == nullptr) | ||
std::__throw_out_of_range("map::at: key not found"); | ||
return static_cast<__node_pointer>(__child)->__get_value().second; | ||
} | ||
|
||
template <class _Arg, | ||
__enable_if_t<__is_transparently_comparable_v<_Compare, key_type, __remove_cvref_t<_Arg> >, int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI const mapped_type& at(_Arg&& __arg) const { | ||
auto [_, __child] = __tree_.__find_equal(__arg); | ||
if (__child == nullptr) | ||
std::__throw_out_of_range("map::at: key not found"); | ||
return static_cast<__node_pointer>(__child)->__get_value().second; | ||
} | ||
|
||
philnik777 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
_LIBCPP_HIDE_FROM_ABI mapped_type& at(const key_type& __k); | ||
_LIBCPP_HIDE_FROM_ABI const mapped_type& at(const key_type& __k) const; | ||
|
||
|
@@ -1242,11 +1268,15 @@ public: | |
_LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __k) { return __tree_.find(__k); } | ||
_LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __k) const { return __tree_.find(__k); } | ||
# if _LIBCPP_STD_VER >= 14 | ||
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0> | ||
template <typename _K2, | ||
enable_if_t<__is_transparent_v<_Compare, _K2> || __is_transparently_comparable_v<_Compare, key_type, _K2>, | ||
Comment on lines
+1271
to
+1272
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is very confusing as-is. The only reason for passing template <class _K2, class _DependentCompare = _Compare, enable_if_t<__is_transparent_v<_DependentCompare>>, ...> If we did that, then we could get rid of the other arguments of Let's do that as a follow-up refactoring, or as a prerequisite for this patch. |
||
int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI iterator find(const _K2& __k) { | ||
return __tree_.find(__k); | ||
} | ||
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0> | ||
template <typename _K2, | ||
enable_if_t<__is_transparent_v<_Compare, _K2> || __is_transparently_comparable_v<_Compare, key_type, _K2>, | ||
int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI const_iterator find(const _K2& __k) const { | ||
return __tree_.find(__k); | ||
} | ||
|
@@ -1262,7 +1292,9 @@ public: | |
|
||
# if _LIBCPP_STD_VER >= 20 | ||
_LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __k) const { return find(__k) != end(); } | ||
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0> | ||
template <typename _K2, | ||
enable_if_t<__is_transparent_v<_Compare, _K2> || __is_transparently_comparable_v<_Compare, key_type, _K2>, | ||
int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI bool contains(const _K2& __k) const { | ||
return find(__k) != end(); | ||
} | ||
|
@@ -1271,12 +1303,16 @@ public: | |
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __k) { return __tree_.lower_bound(__k); } | ||
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __k) const { return __tree_.lower_bound(__k); } | ||
# if _LIBCPP_STD_VER >= 14 | ||
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0> | ||
template <typename _K2, | ||
enable_if_t<__is_transparent_v<_Compare, _K2> || __is_transparently_comparable_v<_Compare, key_type, _K2>, | ||
int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _K2& __k) { | ||
return __tree_.lower_bound(__k); | ||
} | ||
|
||
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0> | ||
template <typename _K2, | ||
enable_if_t<__is_transparent_v<_Compare, _K2> || __is_transparently_comparable_v<_Compare, key_type, _K2>, | ||
int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _K2& __k) const { | ||
return __tree_.lower_bound(__k); | ||
} | ||
|
@@ -1285,11 +1321,15 @@ public: | |
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __k) { return __tree_.upper_bound(__k); } | ||
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __k) const { return __tree_.upper_bound(__k); } | ||
# if _LIBCPP_STD_VER >= 14 | ||
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0> | ||
template <typename _K2, | ||
enable_if_t<__is_transparent_v<_Compare, _K2> || __is_transparently_comparable_v<_Compare, key_type, _K2>, | ||
int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _K2& __k) { | ||
return __tree_.upper_bound(__k); | ||
} | ||
template <typename _K2, enable_if_t<__is_transparent_v<_Compare, _K2>, int> = 0> | ||
template <typename _K2, | ||
enable_if_t<__is_transparent_v<_Compare, _K2> || __is_transparently_comparable_v<_Compare, key_type, _K2>, | ||
int> = 0> | ||
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _K2& __k) const { | ||
return __tree_.upper_bound(__k); | ||
} | ||
|
Uh oh!
There was an error while loading. Please reload this page.