mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-12 21:28:48 +00:00
[libc] Add invoke / invoke_result type traits (#65750)
This commit is contained in:
parent
ea42b49f10
commit
2dbdc9fc85
@ -105,6 +105,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
|
||||
|
@ -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"
|
||||
|
62
libc/src/__support/CPP/type_traits/invoke.h
Normal file
62
libc/src/__support/CPP/type_traits/invoke.h
Normal file
@ -0,0 +1,62 @@
|
||||
//===-- 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/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"
|
||||
|
||||
namespace __llvm_libc::cpp {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Catch all function and functor types.
|
||||
template <class FunctionPtrType> struct invoke_dispatcher {
|
||||
template <class T, class... Args,
|
||||
typename = cpp::enable_if_t<
|
||||
cpp::is_same_v<cpp::decay_t<T>, FunctionPtrType>>>
|
||||
static decltype(auto) call(T &&fun, Args &&...args) {
|
||||
return cpp::forward<T>(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 decltype(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 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>);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
template <class Function, class... Args>
|
||||
decltype(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
|
26
libc/src/__support/CPP/type_traits/invoke_result.h
Normal file
26
libc/src/__support/CPP/type_traits/invoke_result.h
Normal file
@ -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/type_traits/type_identity.h"
|
||||
#include "src/__support/CPP/utility/declval.h"
|
||||
|
||||
namespace __llvm_libc::cpp {
|
||||
|
||||
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;
|
||||
|
||||
} // namespace __llvm_libc::cpp
|
||||
|
||||
#endif // LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H
|
@ -145,6 +145,119 @@ 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;
|
||||
};
|
||||
|
||||
template <int tag> struct Tag {
|
||||
static constexpr int value = 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>(); }
|
||||
|
||||
const Tag<0> &operator()(const Tag<0> &a) { return a; }
|
||||
const Tag<0> &&operator()(const Tag<0> &&a) { return cpp::move(a); }
|
||||
Tag<1> operator()(Tag<1> a) { return a; }
|
||||
};
|
||||
|
||||
} // namespace invoke_detail
|
||||
|
||||
TEST(LlvmLibcTypeTraitsTest, invoke) {
|
||||
using namespace invoke_detail;
|
||||
{ // member function call
|
||||
A a;
|
||||
EXPECT_EQ(a.state, INIT);
|
||||
invoke(&A::apply, a);
|
||||
EXPECT_EQ(a.state, A_APPLY_CALLED);
|
||||
}
|
||||
{ // overriden member function call
|
||||
B b;
|
||||
EXPECT_EQ(b.state, INIT);
|
||||
invoke(&A::apply, b);
|
||||
EXPECT_EQ(b.state, B_APPLY_CALLED);
|
||||
}
|
||||
{ // free function
|
||||
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(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(invoke([]() -> int { return 2; }), 2);
|
||||
EXPECT_EQ(invoke([](int value) -> int { return value; }, 1), 1);
|
||||
|
||||
const auto lambda = [](int) { return 0; };
|
||||
EXPECT_EQ(invoke(lambda, 1), 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(LlvmLibcTypeTraitsTest, invoke_result) {
|
||||
using namespace invoke_detail;
|
||||
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 qualifiers
|
||||
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>>));
|
||||
// Functor with several arg qualifiers
|
||||
EXPECT_TRUE(
|
||||
(is_same_v<invoke_result_t<Functor &&, Tag<0> &>, const Tag<0> &>));
|
||||
EXPECT_TRUE((is_same_v<invoke_result_t<Functor, Tag<0>>, const Tag<0> &&>));
|
||||
EXPECT_TRUE((is_same_v<invoke_result_t<Functor, Tag<1>>, Tag<1>>));
|
||||
{
|
||||
auto lambda = []() {};
|
||||
EXPECT_TRUE((is_same_v<invoke_result_t<decltype(lambda)>, void>));
|
||||
}
|
||||
{
|
||||
auto lambda = []() { return 0; };
|
||||
EXPECT_TRUE((is_same_v<invoke_result_t<decltype(lambda)>, int>));
|
||||
}
|
||||
{
|
||||
auto lambda = [](int) -> double { return 0; };
|
||||
EXPECT_TRUE((is_same_v<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,
|
||||
|
@ -296,6 +296,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",
|
||||
@ -334,6 +336,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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user