[libc-commits] [libc] [libc] add invoke_result type traits (PR #65750)
Guillaume Chatelet via libc-commits
libc-commits at lists.llvm.org
Fri Sep 8 06:13:00 PDT 2023
https://github.com/gchatelet created https://github.com/llvm/llvm-project/pull/65750:
- [libc] Add is_object #65749
- [libc] add invoke_result type traits
>From 3ab691253d62985f86e20c8780ea29b5bbec3c20 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Fri, 8 Sep 2023 11:26:07 +0000
Subject: [PATCH 1/2] [libc] Add is_object
---
libc/src/__support/CPP/type_traits.h | 1 +
.../src/__support/CPP/type_traits/is_object.h | 30 +++++++++++++++++++
.../llvm-project-overlay/libc/BUILD.bazel | 1 +
3 files changed, 32 insertions(+)
create mode 100644 libc/src/__support/CPP/type_traits/is_object.h
diff --git a/libc/src/__support/CPP/type_traits.h b/libc/src/__support/CPP/type_traits.h
index c0d3591f8d37eb8..9deb08b221593e1 100644
--- a/libc/src/__support/CPP/type_traits.h
+++ b/libc/src/__support/CPP/type_traits.h
@@ -32,6 +32,7 @@
#include "src/__support/CPP/type_traits/is_lvalue_reference.h"
#include "src/__support/CPP/type_traits/is_member_pointer.h"
#include "src/__support/CPP/type_traits/is_null_pointer.h"
+#include "src/__support/CPP/type_traits/is_object.h"
#include "src/__support/CPP/type_traits/is_pointer.h"
#include "src/__support/CPP/type_traits/is_reference.h"
#include "src/__support/CPP/type_traits/is_rvalue_reference.h"
diff --git a/libc/src/__support/CPP/type_traits/is_object.h b/libc/src/__support/CPP/type_traits/is_object.h
new file mode 100644
index 000000000000000..9928fb7b85e3d82
--- /dev/null
+++ b/libc/src/__support/CPP/type_traits/is_object.h
@@ -0,0 +1,30 @@
+//===-- is_object 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_IS_OBJECT_H
+#define LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_IS_OBJECT_H
+
+#include "src/__support/CPP/type_traits/bool_constant.h"
+#include "src/__support/CPP/type_traits/is_array.h"
+#include "src/__support/CPP/type_traits/is_class.h"
+#include "src/__support/CPP/type_traits/is_scalar.h"
+#include "src/__support/CPP/type_traits/is_union.h"
+#include "src/__support/macros/attributes.h"
+
+namespace __llvm_libc::cpp {
+
+// is_object
+template <class T>
+struct is_object
+ : cpp::bool_constant<cpp::is_scalar_v<T> || cpp::is_array_v<T> ||
+ cpp::is_union_v<T> || cpp::is_class_v<T>> {};
+template <class T>
+LIBC_INLINE_VAR constexpr bool is_object_v = is_object<T>::value;
+
+} // namespace __llvm_libc::cpp
+
+#endif // LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_IS_OBJECT_H
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 3680ee730e72d54..17e4913749d51c6 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -309,6 +309,7 @@ libc_support_library(
"src/__support/CPP/type_traits/is_lvalue_reference.h",
"src/__support/CPP/type_traits/is_member_pointer.h",
"src/__support/CPP/type_traits/is_null_pointer.h",
+ "src/__support/CPP/type_traits/is_object.h",
"src/__support/CPP/type_traits/is_pointer.h",
"src/__support/CPP/type_traits/is_reference.h",
"src/__support/CPP/type_traits/is_rvalue_reference.h",
>From 07281d72cd500c2cfb55a4c008357ef914f539d5 Mon Sep 17 00:00:00 2001
From: Guillaume Chatelet <gchatelet at google.com>
Date: Fri, 8 Sep 2023 13:10:05 +0000
Subject: [PATCH 2/2] [libc] add invoke_result type traits
---
libc/src/__support/CPP/type_traits.h | 1 +
.../__support/CPP/type_traits/invoke_result.h | 90 +++++++++++++++++++
.../llvm-project-overlay/libc/BUILD.bazel | 2 +
3 files changed, 93 insertions(+)
create mode 100644 libc/src/__support/CPP/type_traits/invoke_result.h
diff --git a/libc/src/__support/CPP/type_traits.h b/libc/src/__support/CPP/type_traits.h
index 9deb08b221593e1..cec5de1198c96f7 100644
--- a/libc/src/__support/CPP/type_traits.h
+++ b/libc/src/__support/CPP/type_traits.h
@@ -18,6 +18,7 @@
#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_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_result.h b/libc/src/__support/CPP/type_traits/invoke_result.h
new file mode 100644
index 000000000000000..47b0ffb88e57390
--- /dev/null
+++ b/libc/src/__support/CPP/type_traits/invoke_result.h
@@ -0,0 +1,90 @@
+//===-- 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/decay.h"
+#include "src/__support/CPP/type_traits/enable_if.h"
+#include "src/__support/CPP/type_traits/false_type.h"
+#include "src/__support/CPP/type_traits/is_base_of.h"
+#include "src/__support/CPP/type_traits/is_function.h"
+#include "src/__support/CPP/type_traits/true_type.h"
+#include "src/__support/CPP/utility/declval.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 {
+
+// invoke_result
+
+namespace detail {
+template <class T> struct is_reference_wrapper : cpp::false_type {};
+
+// Disable specialization on `cpp::reference_wrapper` as it is not yet
+// implemented.
+
+// template <class U> struct
+// is_reference_wrapper<cpp::reference_wrapper<U>> : cpp::true_type {};
+
+template <class T> struct invoke_impl {
+ template <class F, class... Args>
+ static auto call(F &&f, Args &&...args)
+ -> decltype(cpp::forward<F>(f)(cpp::forward<Args>(args)...));
+};
+
+template <class B, class MT> struct invoke_impl<MT B::*> {
+ template <class T, class Td = cpp::decay_t<T>,
+ class = cpp::enable_if_t<cpp::is_base_of_v<B, Td>>>
+ static auto get(T &&t) -> T &&;
+
+ template <class T, class Td = cpp::decay_t<T>,
+ class = cpp::enable_if_t<is_reference_wrapper<Td>::value>>
+ static auto get(T &&t) -> decltype(t.get());
+
+ template <class T, class Td = cpp::decay_t<T>,
+ class = cpp::enable_if_t<!cpp::is_base_of_v<B, Td>>,
+ class = cpp::enable_if_t<!is_reference_wrapper<Td>::value>>
+ static auto get(T &&t) -> decltype(*cpp::forward<T>(t));
+
+ template <class T, class... Args, class MT1,
+ class = cpp::enable_if_t<cpp::is_function_v<MT1>>>
+ static auto call(MT1 B::*pmf, T &&t, Args &&...args)
+ -> decltype((invoke_impl::get(cpp::forward<T>(t)).*
+ pmf)(cpp::forward<Args>(args)...));
+
+ template <class T>
+ static auto call(MT B::*pmd, T &&t)
+ -> decltype(invoke_impl::get(cpp::forward<T>(t)).*pmd);
+};
+
+template <class F, class... Args, class Fd = typename cpp::decay_t<F>>
+auto INVOKE(F &&f, Args &&...args)
+ -> decltype(invoke_impl<Fd>::call(cpp::forward<F>(f),
+ cpp::forward<Args>(args)...));
+
+template <typename AlwaysVoid, typename, typename...> struct invoke_result {};
+template <typename F, typename... Args>
+struct invoke_result<decltype(void(detail::INVOKE(cpp::declval<F>(),
+ cpp::declval<Args>()...))),
+ F, Args...> {
+ using type =
+ decltype(detail::INVOKE(cpp::declval<F>(), cpp::declval<Args>()...));
+};
+} // namespace detail
+
+template <class F, class... ArgTypes>
+struct invoke_result : detail::invoke_result<void, F, ArgTypes...> {};
+
+template <class F, class... ArgTypes>
+using invoke_result_t = typename invoke_result<F, ArgTypes...>::type;
+
+} // namespace __llvm_libc::cpp
+
+#endif // LLVM_LIBC_SRC_SUPPORT_CPP_TYPE_TRAITS_INVOKE_RESULT_H
diff --git a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
index 17e4913749d51c6..da9bdc64fb7815d 100644
--- a/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/libc/BUILD.bazel
@@ -295,6 +295,7 @@ 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_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 +334,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",
More information about the libc-commits
mailing list