Commit 12869443 authored by Anton Bikineev's avatar Anton Bikineev Committed by Commit Bot

base: Rename internal::invoke to internal::InvokeImpl

This is needed to prevent ADL to pick up the candidates from the
internal namespace when an argument is from the internal namespace as
well, which otherwise results in overload resolution ambiguity.

Change-Id: I2866d738d3ad16a528e05bac93d1b0c4153b2013
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2463606Reviewed-by: default avatarPeter Kasting <pkasting@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Commit-Queue: Anton Bikineev <bikineev@chromium.org>
Cr-Commit-Position: refs/heads/master@{#816088}
parent 58ec4a73
...@@ -1664,4 +1664,26 @@ TEST(RangesTest, PrevPermutation) { ...@@ -1664,4 +1664,26 @@ TEST(RangesTest, PrevPermutation) {
EXPECT_THAT(bits, ElementsAre(0, 0, 0, 1, 0)); EXPECT_THAT(bits, ElementsAre(0, 0, 0, 1, 0));
} }
namespace internal {
const auto predicate = [](int value) { return value; };
struct TestPair {
int a;
int b;
};
} // namespace internal
// This is a compilation test that checks that using predicates and projections
// from the base::internal namespace in range algorithms doesn't result in
// ambiguous calls to base::invoke.
TEST(RangesTest, DontClashWithPredicateFromInternalInvoke) {
{
int input[] = {0, 1, 2};
ranges::any_of(input, internal::predicate);
}
{
internal::TestPair input[] = {{1, 2}, {3, 4}};
ranges::any_of(input, base::identity{}, &internal::TestPair::a);
}
}
} // namespace base } // namespace base
...@@ -221,7 +221,7 @@ template <typename F, ...@@ -221,7 +221,7 @@ template <typename F,
typename T1, typename T1,
typename... Args, typename... Args,
EnableIf<IsMemFunPtr<F> && IsMemPtrToBaseOf<F, T1>> = true> EnableIf<IsMemFunPtr<F> && IsMemPtrToBaseOf<F, T1>> = true>
constexpr decltype(auto) invoke(F&& f, T1&& t1, Args&&... args) { constexpr decltype(auto) InvokeImpl(F&& f, T1&& t1, Args&&... args) {
return (std::forward<T1>(t1).*f)(std::forward<Args>(args)...); return (std::forward<T1>(t1).*f)(std::forward<Args>(args)...);
} }
...@@ -233,7 +233,7 @@ template <typename F, ...@@ -233,7 +233,7 @@ template <typename F,
typename T1, typename T1,
typename... Args, typename... Args,
EnableIf<IsMemFunPtr<F> && IsRefWrapper<T1>> = true> EnableIf<IsMemFunPtr<F> && IsRefWrapper<T1>> = true>
constexpr decltype(auto) invoke(F&& f, T1&& t1, Args&&... args) { constexpr decltype(auto) InvokeImpl(F&& f, T1&& t1, Args&&... args) {
return (t1.get().*f)(std::forward<Args>(args)...); return (t1.get().*f)(std::forward<Args>(args)...);
} }
...@@ -246,7 +246,7 @@ template <typename F, ...@@ -246,7 +246,7 @@ template <typename F,
typename... Args, typename... Args,
EnableIf<IsMemFunPtr<F> && !IsMemPtrToBaseOf<F, T1> && EnableIf<IsMemFunPtr<F> && !IsMemPtrToBaseOf<F, T1> &&
!IsRefWrapper<T1>> = true> !IsRefWrapper<T1>> = true>
constexpr decltype(auto) invoke(F&& f, T1&& t1, Args&&... args) { constexpr decltype(auto) InvokeImpl(F&& f, T1&& t1, Args&&... args) {
return ((*std::forward<T1>(t1)).*f)(std::forward<Args>(args)...); return ((*std::forward<T1>(t1)).*f)(std::forward<Args>(args)...);
} }
...@@ -257,7 +257,7 @@ constexpr decltype(auto) invoke(F&& f, T1&& t1, Args&&... args) { ...@@ -257,7 +257,7 @@ constexpr decltype(auto) invoke(F&& f, T1&& t1, Args&&... args) {
template <typename F, template <typename F,
typename T1, typename T1,
EnableIf<IsMemObjPtr<F> && IsMemPtrToBaseOf<F, T1>> = true> EnableIf<IsMemObjPtr<F> && IsMemPtrToBaseOf<F, T1>> = true>
constexpr decltype(auto) invoke(F&& f, T1&& t1) { constexpr decltype(auto) InvokeImpl(F&& f, T1&& t1) {
return std::forward<T1>(t1).*f; return std::forward<T1>(t1).*f;
} }
...@@ -268,7 +268,7 @@ constexpr decltype(auto) invoke(F&& f, T1&& t1) { ...@@ -268,7 +268,7 @@ constexpr decltype(auto) invoke(F&& f, T1&& t1) {
template <typename F, template <typename F,
typename T1, typename T1,
EnableIf<IsMemObjPtr<F> && IsRefWrapper<T1>> = true> EnableIf<IsMemObjPtr<F> && IsRefWrapper<T1>> = true>
constexpr decltype(auto) invoke(F&& f, T1&& t1) { constexpr decltype(auto) InvokeImpl(F&& f, T1&& t1) {
return t1.get().*f; return t1.get().*f;
} }
...@@ -280,7 +280,7 @@ template <typename F, ...@@ -280,7 +280,7 @@ template <typename F,
typename T1, typename T1,
EnableIf<IsMemObjPtr<F> && !IsMemPtrToBaseOf<F, T1> && EnableIf<IsMemObjPtr<F> && !IsMemPtrToBaseOf<F, T1> &&
!IsRefWrapper<T1>> = true> !IsRefWrapper<T1>> = true>
constexpr decltype(auto) invoke(F&& f, T1&& t1) { constexpr decltype(auto) InvokeImpl(F&& f, T1&& t1) {
return (*std::forward<T1>(t1)).*f; return (*std::forward<T1>(t1)).*f;
} }
...@@ -289,7 +289,7 @@ constexpr decltype(auto) invoke(F&& f, T1&& t1) { ...@@ -289,7 +289,7 @@ constexpr decltype(auto) invoke(F&& f, T1&& t1) {
// //
// Reference: https://wg21.link/func.require#1.7 // Reference: https://wg21.link/func.require#1.7
template <typename F, typename... Args> template <typename F, typename... Args>
constexpr decltype(auto) invoke(F&& f, Args&&... args) { constexpr decltype(auto) InvokeImpl(F&& f, Args&&... args) {
return std::forward<F>(f)(std::forward<Args>(args)...); return std::forward<F>(f)(std::forward<Args>(args)...);
} }
...@@ -305,7 +305,7 @@ constexpr decltype(auto) invoke(F&& f, Args&&... args) { ...@@ -305,7 +305,7 @@ constexpr decltype(auto) invoke(F&& f, Args&&... args) {
// - https://wg21.link/func.invoke // - https://wg21.link/func.invoke
template <typename F, typename... Args> template <typename F, typename... Args>
constexpr decltype(auto) invoke(F&& f, Args&&... args) { constexpr decltype(auto) invoke(F&& f, Args&&... args) {
return internal::invoke(std::forward<F>(f), std::forward<Args>(args)...); return internal::InvokeImpl(std::forward<F>(f), std::forward<Args>(args)...);
} }
// Implementation of C++20's std::identity. // Implementation of C++20's std::identity.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment