Skip to content

Commit 07281d7

Browse files
committed
[libc] add invoke_result type traits
1 parent 3ab6912 commit 07281d7

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

libc/src/__support/CPP/type_traits.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "src/__support/CPP/type_traits/enable_if.h"
1919
#include "src/__support/CPP/type_traits/false_type.h"
2020
#include "src/__support/CPP/type_traits/integral_constant.h"
21+
#include "src/__support/CPP/type_traits/invoke_result.h"
2122
#include "src/__support/CPP/type_traits/is_arithmetic.h"
2223
#include "src/__support/CPP/type_traits/is_array.h"
2324
#include "src/__support/CPP/type_traits/is_base_of.h"
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//===-- invoke_result type_traits -------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
#ifndef LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H
9+
#define LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H
10+
11+
#include "src/__support/CPP/type_traits/decay.h"
12+
#include "src/__support/CPP/type_traits/enable_if.h"
13+
#include "src/__support/CPP/type_traits/false_type.h"
14+
#include "src/__support/CPP/type_traits/is_base_of.h"
15+
#include "src/__support/CPP/type_traits/is_function.h"
16+
#include "src/__support/CPP/type_traits/true_type.h"
17+
#include "src/__support/CPP/utility/declval.h"
18+
#include "src/__support/CPP/utility/forward.h"
19+
20+
// BEWARE : this implementation is not fully conformant as it doesn't take
21+
// `cpp::reference_wrapper` into account.
22+
23+
namespace __llvm_libc::cpp {
24+
25+
// invoke_result
26+
27+
namespace detail {
28+
template <class T> struct is_reference_wrapper : cpp::false_type {};
29+
30+
// Disable specialization on `cpp::reference_wrapper` as it is not yet
31+
// implemented.
32+
33+
// template <class U> struct
34+
// is_reference_wrapper<cpp::reference_wrapper<U>> : cpp::true_type {};
35+
36+
template <class T> struct invoke_impl {
37+
template <class F, class... Args>
38+
static auto call(F &&f, Args &&...args)
39+
-> decltype(cpp::forward<F>(f)(cpp::forward<Args>(args)...));
40+
};
41+
42+
template <class B, class MT> struct invoke_impl<MT B::*> {
43+
template <class T, class Td = cpp::decay_t<T>,
44+
class = cpp::enable_if_t<cpp::is_base_of_v<B, Td>>>
45+
static auto get(T &&t) -> T &&;
46+
47+
template <class T, class Td = cpp::decay_t<T>,
48+
class = cpp::enable_if_t<is_reference_wrapper<Td>::value>>
49+
static auto get(T &&t) -> decltype(t.get());
50+
51+
template <class T, class Td = cpp::decay_t<T>,
52+
class = cpp::enable_if_t<!cpp::is_base_of_v<B, Td>>,
53+
class = cpp::enable_if_t<!is_reference_wrapper<Td>::value>>
54+
static auto get(T &&t) -> decltype(*cpp::forward<T>(t));
55+
56+
template <class T, class... Args, class MT1,
57+
class = cpp::enable_if_t<cpp::is_function_v<MT1>>>
58+
static auto call(MT1 B::*pmf, T &&t, Args &&...args)
59+
-> decltype((invoke_impl::get(cpp::forward<T>(t)).*
60+
pmf)(cpp::forward<Args>(args)...));
61+
62+
template <class T>
63+
static auto call(MT B::*pmd, T &&t)
64+
-> decltype(invoke_impl::get(cpp::forward<T>(t)).*pmd);
65+
};
66+
67+
template <class F, class... Args, class Fd = typename cpp::decay_t<F>>
68+
auto INVOKE(F &&f, Args &&...args)
69+
-> decltype(invoke_impl<Fd>::call(cpp::forward<F>(f),
70+
cpp::forward<Args>(args)...));
71+
72+
template <typename AlwaysVoid, typename, typename...> struct invoke_result {};
73+
template <typename F, typename... Args>
74+
struct invoke_result<decltype(void(detail::INVOKE(cpp::declval<F>(),
75+
cpp::declval<Args>()...))),
76+
F, Args...> {
77+
using type =
78+
decltype(detail::INVOKE(cpp::declval<F>(), cpp::declval<Args>()...));
79+
};
80+
} // namespace detail
81+
82+
template <class F, class... ArgTypes>
83+
struct invoke_result : detail::invoke_result<void, F, ArgTypes...> {};
84+
85+
template <class F, class... ArgTypes>
86+
using invoke_result_t = typename invoke_result<F, ArgTypes...>::type;
87+
88+
} // namespace __llvm_libc::cpp
89+
90+
#endif // LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H

utils/bazel/llvm-project-overlay/libc/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ libc_support_library(
295295
"src/__support/CPP/type_traits/enable_if.h",
296296
"src/__support/CPP/type_traits/false_type.h",
297297
"src/__support/CPP/type_traits/integral_constant.h",
298+
"src/__support/CPP/type_traits/invoke_result.h",
298299
"src/__support/CPP/type_traits/is_arithmetic.h",
299300
"src/__support/CPP/type_traits/is_array.h",
300301
"src/__support/CPP/type_traits/is_base_of.h",
@@ -333,6 +334,7 @@ libc_support_library(
333334
"src/__support/CPP/type_traits/type_identity.h",
334335
"src/__support/CPP/type_traits/void_t.h",
335336
"src/__support/CPP/utility/declval.h",
337+
"src/__support/CPP/utility/forward.h",
336338
],
337339
deps = [
338340
":__support_macros_attributes",

0 commit comments

Comments
 (0)