https://github.com/gchatelet updated https://github.com/llvm/llvm-project/pull/65750:
>From 5023264dce58aaa46b18404a4578b7a777962758 Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet <gchate...@google.com> Date: Fri, 8 Sep 2023 13:10:05 +0000 Subject: [PATCH 1/4] [libc] add invoke / invoke_result type traits --- libc/src/__support/CPP/CMakeLists.txt | 2 + libc/src/__support/CPP/type_traits.h | 2 + libc/src/__support/CPP/type_traits/invoke.h | 58 +++++++++++++ .../__support/CPP/type_traits/invoke_result.h | 26 ++++++ .../src/__support/CPP/type_traits_test.cpp | 86 +++++++++++++++++++ .../llvm-project-overlay/libc/BUILD.bazel | 3 + 6 files changed, 177 insertions(+) create mode 100644 libc/src/__support/CPP/type_traits/invoke.h create mode 100644 libc/src/__support/CPP/type_traits/invoke_result.h diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt index d24c023ec28ebc9..bb330a7b0ac5106 100644 --- a/libc/src/__support/CPP/CMakeLists.txt +++ b/libc/src/__support/CPP/CMakeLists.txt @@ -104,6 +104,8 @@ add_header_library( type_traits/enable_if.h type_traits/false_type.h type_traits/integral_constant.h + type_traits/invoke.h + type_traits/invoke_result.h type_traits/is_arithmetic.h type_traits/is_array.h type_traits/is_base_of.h diff --git a/libc/src/__support/CPP/type_traits.h b/libc/src/__support/CPP/type_traits.h index 9deb08b221593e1..3de2ca58903184c 100644 --- a/libc/src/__support/CPP/type_traits.h +++ b/libc/src/__support/CPP/type_traits.h @@ -18,6 +18,8 @@ #include "src/__support/CPP/type_traits/enable_if.h" #include "src/__support/CPP/type_traits/false_type.h" #include "src/__support/CPP/type_traits/integral_constant.h" +#include "src/__support/CPP/type_traits/invoke.h" +#include "src/__support/CPP/type_traits/invoke_result.h" #include "src/__support/CPP/type_traits/is_arithmetic.h" #include "src/__support/CPP/type_traits/is_array.h" #include "src/__support/CPP/type_traits/is_base_of.h" diff --git a/libc/src/__support/CPP/type_traits/invoke.h b/libc/src/__support/CPP/type_traits/invoke.h new file mode 100644 index 000000000000000..e1f661339f349e7 --- /dev/null +++ b/libc/src/__support/CPP/type_traits/invoke.h @@ -0,0 +1,58 @@ +//===-- invoke type_traits --------------------------------------*- 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 LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_H +#define LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_H + +#include "src/__support/CPP/type_traits/decay.h" +#include "src/__support/CPP/type_traits/is_base_of.h" +#include "src/__support/CPP/utility/forward.h" + +// BEWARE : this implementation is not fully conformant as it doesn't take +// `cpp::reference_wrapper` into account. + +namespace __llvm_libc::cpp { + +namespace detail { + +// Catch all function types. +template <class FunctionPtrType> struct invoke_dispatcher { + template <class... Args> + static auto call(FunctionPtrType &&fun, Args &&...args) { + return cpp::forward<FunctionPtrType>(fun)(cpp::forward<Args>(args)...); + } +}; + +// Catch pointer to member function types. +template <class Class, class FunctionReturnType> +struct invoke_dispatcher<FunctionReturnType Class::*> { + using FunctionPtrType = FunctionReturnType Class::*; + + template <class T, class... Args, class DecayT = cpp::decay_t<T>> + static auto call(FunctionPtrType fun, T &&t1, Args &&...args) { + if constexpr (cpp::is_base_of_v<Class, DecayT>) { + // T is a (possibly cv ref) type. + return (cpp::forward<T>(t1).*fun)(cpp::forward<Args>(args)...); + } else { + // T is assumed to be a pointer type. + return (*cpp::forward<T>(t1).*fun)(cpp::forward<Args>(args)...); + } + } +}; + +} // namespace detail + +template <class Function, class... Args> +auto invoke(Function &&fun, Args &&...args) { + return detail::invoke_dispatcher<cpp::decay_t<Function>>::call( + cpp::forward<Function>(fun), cpp::forward<Args>(args)...); +} + +} // namespace __llvm_libc::cpp + +#endif // LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_H diff --git a/libc/src/__support/CPP/type_traits/invoke_result.h b/libc/src/__support/CPP/type_traits/invoke_result.h new file mode 100644 index 000000000000000..1a071f5cb94836f --- /dev/null +++ b/libc/src/__support/CPP/type_traits/invoke_result.h @@ -0,0 +1,26 @@ +//===-- invoke_result type_traits -------------------------------*- 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 LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H +#define LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H + +#include "src/__support/CPP/type_traits/invoke.h" +#include "src/__support/CPP/utility/declval.h" + +namespace __llvm_libc::cpp { + +template <class F, class... Args> struct invoke_result { + using type = + decltype(cpp::invoke(cpp::declval<F>(), cpp::declval<Args>()...)); +}; + +template <class F, class... Args> +using invoke_result_t = typename invoke_result<F, Args...>::type; + +} // namespace __llvm_libc::cpp + +#endif // LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H diff --git a/libc/test/src/__support/CPP/type_traits_test.cpp b/libc/test/src/__support/CPP/type_traits_test.cpp index cd025f588388d68..3c1a25b5a1033e9 100644 --- a/libc/test/src/__support/CPP/type_traits_test.cpp +++ b/libc/test/src/__support/CPP/type_traits_test.cpp @@ -145,6 +145,92 @@ TEST(LlvmLibcTypeTraitsTest, integral_constant) { EXPECT_EQ((integral_constant<int, 4>::value), 4); } +namespace invoke_detail { + +enum State { INIT = 0, A_APPLY_CALLED, B_APPLY_CALLED }; + +struct A { + State state = INIT; + virtual ~A() {} + virtual void apply() { state = A_APPLY_CALLED; } +}; + +struct B : public A { + virtual ~B() {} + virtual void apply() { state = B_APPLY_CALLED; } +}; + +void free_function() {} +int free_function_return_5() { return 5; } +int free_function_passtrough(int value) { return value; } + +struct Delegate { + int (*ptr)(int) = &free_function_passtrough; +}; + +} // namespace invoke_detail + +TEST(LlvmLibcTypeTraitsTest, invoke) { + using namespace invoke_detail; + { // member function call + A a; + EXPECT_EQ(a.state, INIT); + cpp::invoke(&A::apply, a); + EXPECT_EQ(a.state, A_APPLY_CALLED); + } + { // overriden member function call + B b; + EXPECT_EQ(b.state, INIT); + cpp::invoke(&A::apply, b); + EXPECT_EQ(b.state, B_APPLY_CALLED); + } + { // free function + cpp::invoke(&free_function); + EXPECT_EQ(cpp::invoke(&free_function_return_5), 5); + EXPECT_EQ(cpp::invoke(&free_function_passtrough, 1), 1); + } + { // pointer member function call + Delegate d; + EXPECT_EQ(cpp::invoke(&Delegate::ptr, d, 2), 2); + } + { // lambda + EXPECT_EQ(cpp::invoke([]() -> int { return 2; }), 2); + EXPECT_EQ(cpp::invoke([](int value) -> int { return value; }, 1), 1); + } +} + +TEST(LlvmLibcTypeTraitsTest, invoke_result) { + using namespace invoke_detail; + EXPECT_TRUE( + (cpp::is_same_v<cpp::invoke_result_t<decltype(&A::apply), A>, void>)); + EXPECT_TRUE( + (cpp::is_same_v<cpp::invoke_result_t<decltype(&A::apply), B>, void>)); + EXPECT_TRUE( + (cpp::is_same_v<cpp::invoke_result_t<decltype(&free_function)>, void>)); + EXPECT_TRUE( + (cpp::is_same_v<cpp::invoke_result_t<decltype(&free_function_return_5)>, + int>)); + EXPECT_TRUE((cpp::is_same_v< + cpp::invoke_result_t<decltype(&free_function_passtrough), int>, + int>)); + EXPECT_TRUE( + (cpp::is_same_v< + cpp::invoke_result_t<decltype(&Delegate::ptr), Delegate, int>, int>)); + { + auto lambda = []() {}; + EXPECT_TRUE((cpp::is_same_v<cpp::invoke_result_t<decltype(lambda)>, void>)); + } + { + auto lambda = []() { return 0; }; + EXPECT_TRUE((cpp::is_same_v<cpp::invoke_result_t<decltype(lambda)>, int>)); + } + { + auto lambda = [](int) -> double { return 0; }; + EXPECT_TRUE( + (cpp::is_same_v<cpp::invoke_result_t<decltype(lambda), int>, double>)); + } +} + using IntegralAndFloatingTypes = testing::TypeList<bool, char, short, int, long, long long, unsigned char, unsigned short, unsigned int, unsigned long, diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 17e4913749d51c6..06cabc015decf30 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -295,6 +295,8 @@ libc_support_library( "src/__support/CPP/type_traits/enable_if.h", "src/__support/CPP/type_traits/false_type.h", "src/__support/CPP/type_traits/integral_constant.h", + "src/__support/CPP/type_traits/invoke.h", + "src/__support/CPP/type_traits/invoke_result.h", "src/__support/CPP/type_traits/is_arithmetic.h", "src/__support/CPP/type_traits/is_array.h", "src/__support/CPP/type_traits/is_base_of.h", @@ -333,6 +335,7 @@ libc_support_library( "src/__support/CPP/type_traits/type_identity.h", "src/__support/CPP/type_traits/void_t.h", "src/__support/CPP/utility/declval.h", + "src/__support/CPP/utility/forward.h", ], deps = [ ":__support_macros_attributes", >From 61c3889d618fe9695d8ee86ecd8197555bdabb75 Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet <gchate...@google.com> Date: Wed, 13 Sep 2023 13:11:19 +0000 Subject: [PATCH 2/4] Fix missing forwarding reference --- libc/src/__support/CPP/type_traits/invoke.h | 15 ++++++++------- libc/test/src/__support/CPP/type_traits_test.cpp | 3 +++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/libc/src/__support/CPP/type_traits/invoke.h b/libc/src/__support/CPP/type_traits/invoke.h index e1f661339f349e7..0d66e5655594652 100644 --- a/libc/src/__support/CPP/type_traits/invoke.h +++ b/libc/src/__support/CPP/type_traits/invoke.h @@ -10,21 +10,22 @@ #define LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_H #include "src/__support/CPP/type_traits/decay.h" +#include "src/__support/CPP/type_traits/enable_if.h" #include "src/__support/CPP/type_traits/is_base_of.h" +#include "src/__support/CPP/type_traits/is_same.h" #include "src/__support/CPP/utility/forward.h" -// BEWARE : this implementation is not fully conformant as it doesn't take -// `cpp::reference_wrapper` into account. - namespace __llvm_libc::cpp { namespace detail { -// Catch all function types. +// Catch all function and functor types. template <class FunctionPtrType> struct invoke_dispatcher { - template <class... Args> - static auto call(FunctionPtrType &&fun, Args &&...args) { - return cpp::forward<FunctionPtrType>(fun)(cpp::forward<Args>(args)...); + template <class T, class... Args, + typename = cpp::enable_if_t< + cpp::is_same_v<cpp::decay_t<T>, FunctionPtrType>>> + static auto call(T &&fun, Args &&...args) { + return cpp::forward<T>(fun)(cpp::forward<Args>(args)...); } }; diff --git a/libc/test/src/__support/CPP/type_traits_test.cpp b/libc/test/src/__support/CPP/type_traits_test.cpp index 3c1a25b5a1033e9..04ee3aba68e51ea 100644 --- a/libc/test/src/__support/CPP/type_traits_test.cpp +++ b/libc/test/src/__support/CPP/type_traits_test.cpp @@ -196,6 +196,9 @@ TEST(LlvmLibcTypeTraitsTest, invoke) { { // lambda EXPECT_EQ(cpp::invoke([]() -> int { return 2; }), 2); EXPECT_EQ(cpp::invoke([](int value) -> int { return value; }, 1), 1); + + const auto lambda = [](int) { return 0; }; + EXPECT_EQ(cpp::invoke(lambda, 1), 0); } } >From 74d7f1b76a35967f61dc1a364576b39c11364285 Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet <gchate...@google.com> Date: Wed, 13 Sep 2023 13:42:55 +0000 Subject: [PATCH 3/4] Enforce assumption --- libc/src/__support/CPP/CMakeLists.txt | 1 + .../__support/CPP/type_traits/always_false.h | 25 +++++++++++++++++++ libc/src/__support/CPP/type_traits/invoke.h | 8 ++++-- libc/src/__support/CPP/utility/declval.h | 8 ++---- .../llvm-project-overlay/libc/BUILD.bazel | 1 + 5 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 libc/src/__support/CPP/type_traits/always_false.h diff --git a/libc/src/__support/CPP/CMakeLists.txt b/libc/src/__support/CPP/CMakeLists.txt index bb330a7b0ac5106..a2d3bd7df9e9069 100644 --- a/libc/src/__support/CPP/CMakeLists.txt +++ b/libc/src/__support/CPP/CMakeLists.txt @@ -95,6 +95,7 @@ add_header_library( type_traits HDRS type_traits.h + type_traits/always_false.h type_traits/add_lvalue_reference.h type_traits/add_pointer.h type_traits/add_rvalue_reference.h diff --git a/libc/src/__support/CPP/type_traits/always_false.h b/libc/src/__support/CPP/type_traits/always_false.h new file mode 100644 index 000000000000000..84be58d16ec8da6 --- /dev/null +++ b/libc/src/__support/CPP/type_traits/always_false.h @@ -0,0 +1,25 @@ +//===-- convenient static_assert(false) helper ------------------*- 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 LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_ALWAYS_FALSE_H +#define LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_ALWAYS_FALSE_H + +#include "src/__support/macros/attributes.h" + +namespace __llvm_libc::cpp { + +// This is technically not part of the standard but it come often enough that +// it's convenient to have around. +// +// https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2593r0.html#valid-workaround + +template <typename...> LIBC_INLINE_VAR constexpr bool always_false = false; + +} // namespace __llvm_libc::cpp + +#endif // LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_ALWAYS_FALSE_H diff --git a/libc/src/__support/CPP/type_traits/invoke.h b/libc/src/__support/CPP/type_traits/invoke.h index 0d66e5655594652..5372a7f60980e23 100644 --- a/libc/src/__support/CPP/type_traits/invoke.h +++ b/libc/src/__support/CPP/type_traits/invoke.h @@ -9,9 +9,11 @@ #ifndef LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_H #define LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_H +#include "src/__support/CPP/type_traits/always_false.h" #include "src/__support/CPP/type_traits/decay.h" #include "src/__support/CPP/type_traits/enable_if.h" #include "src/__support/CPP/type_traits/is_base_of.h" +#include "src/__support/CPP/type_traits/is_pointer.h" #include "src/__support/CPP/type_traits/is_same.h" #include "src/__support/CPP/utility/forward.h" @@ -39,9 +41,11 @@ struct invoke_dispatcher<FunctionReturnType Class::*> { if constexpr (cpp::is_base_of_v<Class, DecayT>) { // T is a (possibly cv ref) type. return (cpp::forward<T>(t1).*fun)(cpp::forward<Args>(args)...); - } else { - // T is assumed to be a pointer type. + } else if constexpr (cpp::is_pointer_v<T>) { + // T is a pointer type. return (*cpp::forward<T>(t1).*fun)(cpp::forward<Args>(args)...); + } else { + static_assert(cpp::always_false<T>); } } }; diff --git a/libc/src/__support/CPP/utility/declval.h b/libc/src/__support/CPP/utility/declval.h index 9261ceb9332d518..21bb973de0dd048 100644 --- a/libc/src/__support/CPP/utility/declval.h +++ b/libc/src/__support/CPP/utility/declval.h @@ -9,17 +9,13 @@ #define LLVM_LIBC_SRC_SUPPORT_CPP_UTILITY_DECLVAL_H #include "src/__support/CPP/type_traits/add_rvalue_reference.h" -#include "src/__support/macros/attributes.h" +#include "src/__support/CPP/type_traits/always_false.h" namespace __llvm_libc::cpp { // declval -namespace detail { -template <typename T> LIBC_INLINE_VAR constexpr bool always_false = false; -} - template <typename T> cpp::add_rvalue_reference_t<T> declval() { - static_assert(detail::always_false<T>, + static_assert(cpp::always_false<T>, "declval not allowed in an evaluated context"); } diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel index 06cabc015decf30..80ea75ecd8760e0 100644 --- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel @@ -289,6 +289,7 @@ libc_support_library( "src/__support/CPP/type_traits/add_lvalue_reference.h", "src/__support/CPP/type_traits/add_pointer.h", "src/__support/CPP/type_traits/add_rvalue_reference.h", + "src/__support/CPP/type_traits/always_false.h", "src/__support/CPP/type_traits/bool_constant.h", "src/__support/CPP/type_traits/conditional.h", "src/__support/CPP/type_traits/decay.h", >From 485ecc2040819b0669cf1aa02743412745547c6a Mon Sep 17 00:00:00 2001 From: Guillaume Chatelet <gchate...@google.com> Date: Thu, 14 Sep 2023 11:38:03 +0000 Subject: [PATCH 4/4] Add tests in the presence of several ref qualifiers --- .../__support/CPP/type_traits/invoke_result.h | 8 +-- .../src/__support/CPP/type_traits_test.cpp | 71 +++++++++++-------- 2 files changed, 47 insertions(+), 32 deletions(-) diff --git a/libc/src/__support/CPP/type_traits/invoke_result.h b/libc/src/__support/CPP/type_traits/invoke_result.h index 1a071f5cb94836f..20ebba4e4cf95cf 100644 --- a/libc/src/__support/CPP/type_traits/invoke_result.h +++ b/libc/src/__support/CPP/type_traits/invoke_result.h @@ -9,14 +9,14 @@ #define LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H #include "src/__support/CPP/type_traits/invoke.h" +#include "src/__support/CPP/type_traits/type_identity.h" #include "src/__support/CPP/utility/declval.h" namespace __llvm_libc::cpp { -template <class F, class... Args> struct invoke_result { - using type = - decltype(cpp::invoke(cpp::declval<F>(), cpp::declval<Args>()...)); -}; +template <class F, class... Args> +struct invoke_result : cpp::type_identity<decltype(cpp::invoke( + cpp::declval<F>(), cpp::declval<Args>()...))> {}; template <class F, class... Args> using invoke_result_t = typename invoke_result<F, Args...>::type; diff --git a/libc/test/src/__support/CPP/type_traits_test.cpp b/libc/test/src/__support/CPP/type_traits_test.cpp index 04ee3aba68e51ea..e18004fa4bace0b 100644 --- a/libc/test/src/__support/CPP/type_traits_test.cpp +++ b/libc/test/src/__support/CPP/type_traits_test.cpp @@ -168,6 +168,17 @@ struct Delegate { int (*ptr)(int) = &free_function_passtrough; }; +template <int tag> struct Tag { + static int value() { return tag; } +}; + +struct Functor { + auto operator()() & { return Tag<0>(); } + auto operator()() const & { return Tag<1>(); } + auto operator()() && { return Tag<2>(); } + auto operator()() const && { return Tag<3>(); } +}; + } // namespace invoke_detail TEST(LlvmLibcTypeTraitsTest, invoke) { @@ -175,62 +186,66 @@ TEST(LlvmLibcTypeTraitsTest, invoke) { { // member function call A a; EXPECT_EQ(a.state, INIT); - cpp::invoke(&A::apply, a); + invoke(&A::apply, a); EXPECT_EQ(a.state, A_APPLY_CALLED); } { // overriden member function call B b; EXPECT_EQ(b.state, INIT); - cpp::invoke(&A::apply, b); + invoke(&A::apply, b); EXPECT_EQ(b.state, B_APPLY_CALLED); } { // free function - cpp::invoke(&free_function); - EXPECT_EQ(cpp::invoke(&free_function_return_5), 5); - EXPECT_EQ(cpp::invoke(&free_function_passtrough, 1), 1); + invoke(&free_function); + EXPECT_EQ(invoke(&free_function_return_5), 5); + EXPECT_EQ(invoke(&free_function_passtrough, 1), 1); } { // pointer member function call Delegate d; - EXPECT_EQ(cpp::invoke(&Delegate::ptr, d, 2), 2); + EXPECT_EQ(invoke(&Delegate::ptr, d, 2), 2); + } + { // Functor with several ref qualifier + Functor f; + const Functor cf; + EXPECT_EQ(invoke(f).value(), 0); + EXPECT_EQ(invoke(cf).value(), 1); + EXPECT_EQ(invoke(move(f)).value(), 2); + EXPECT_EQ(invoke(move(cf)).value(), 3); } { // lambda - EXPECT_EQ(cpp::invoke([]() -> int { return 2; }), 2); - EXPECT_EQ(cpp::invoke([](int value) -> int { return value; }, 1), 1); + EXPECT_EQ(invoke([]() -> int { return 2; }), 2); + EXPECT_EQ(invoke([](int value) -> int { return value; }, 1), 1); const auto lambda = [](int) { return 0; }; - EXPECT_EQ(cpp::invoke(lambda, 1), 0); + EXPECT_EQ(invoke(lambda, 1), 0); } } TEST(LlvmLibcTypeTraitsTest, invoke_result) { using namespace invoke_detail; - EXPECT_TRUE( - (cpp::is_same_v<cpp::invoke_result_t<decltype(&A::apply), A>, void>)); - EXPECT_TRUE( - (cpp::is_same_v<cpp::invoke_result_t<decltype(&A::apply), B>, void>)); - EXPECT_TRUE( - (cpp::is_same_v<cpp::invoke_result_t<decltype(&free_function)>, void>)); - EXPECT_TRUE( - (cpp::is_same_v<cpp::invoke_result_t<decltype(&free_function_return_5)>, - int>)); - EXPECT_TRUE((cpp::is_same_v< - cpp::invoke_result_t<decltype(&free_function_passtrough), int>, - int>)); - EXPECT_TRUE( - (cpp::is_same_v< - cpp::invoke_result_t<decltype(&Delegate::ptr), Delegate, int>, int>)); + EXPECT_TRUE((is_same_v<invoke_result_t<void (A::*)(), A>, void>)); + EXPECT_TRUE((is_same_v<invoke_result_t<void (A::*)(), B>, void>)); + EXPECT_TRUE((is_same_v<invoke_result_t<void (*)()>, void>)); + EXPECT_TRUE((is_same_v<invoke_result_t<int (*)()>, int>)); + EXPECT_TRUE((is_same_v<invoke_result_t<int (*)(int), int>, int>)); + EXPECT_TRUE(( + is_same_v<invoke_result_t<int (*Delegate::*)(int), Delegate, int>, int>)); + // Functor with several ref qualifier + EXPECT_TRUE((is_same_v<invoke_result_t<Functor &>, Tag<0>>)); + EXPECT_TRUE((is_same_v<invoke_result_t<Functor const &>, Tag<1>>)); + EXPECT_TRUE((is_same_v<invoke_result_t<Functor &&>, Tag<2>>)); + EXPECT_TRUE((is_same_v<invoke_result_t<Functor const &&>, Tag<3>>)); { auto lambda = []() {}; - EXPECT_TRUE((cpp::is_same_v<cpp::invoke_result_t<decltype(lambda)>, void>)); + EXPECT_TRUE((is_same_v<invoke_result_t<decltype(lambda)>, void>)); } { auto lambda = []() { return 0; }; - EXPECT_TRUE((cpp::is_same_v<cpp::invoke_result_t<decltype(lambda)>, int>)); + EXPECT_TRUE((is_same_v<invoke_result_t<decltype(lambda)>, int>)); } { auto lambda = [](int) -> double { return 0; }; - EXPECT_TRUE( - (cpp::is_same_v<cpp::invoke_result_t<decltype(lambda), int>, double>)); + EXPECT_TRUE((is_same_v<invoke_result_t<decltype(lambda), int>, double>)); } } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits