[libcxx-commits] [libcxx] 08920cc - [libc++] Add __is_callable type trait and begin granularizing type_traits
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Apr 8 03:24:07 PDT 2022
Author: Nikolas Klauser
Date: 2022-04-08T12:23:52+02:00
New Revision: 08920cc04343e69ee8a56168a5911acddf40e6ba
URL: https://github.com/llvm/llvm-project/commit/08920cc04343e69ee8a56168a5911acddf40e6ba
DIFF: https://github.com/llvm/llvm-project/commit/08920cc04343e69ee8a56168a5911acddf40e6ba.diff
LOG: [libc++] Add __is_callable type trait and begin granularizing type_traits
`__is_callable` is required to ensure that the classic algorithms are only called with functions or functors. I also begin to granularize `<type_traits>`.
Reviewed By: ldionne, #libc
Spies: libcxx-commits, mgorny
Differential Revision: https://reviews.llvm.org/D123114
Added:
libcxx/include/__type_traits/integral_constant.h
libcxx/include/__type_traits/is_callable.h
libcxx/test/libcxx/type_traits/is_callable.compile.pass.cpp
Modified:
libcxx/include/CMakeLists.txt
libcxx/include/module.modulemap
libcxx/include/type_traits
libcxx/test/libcxx/private_headers.verify.cpp
Removed:
################################################################################
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index be544cfd288e6..5069d06d894b4 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -411,6 +411,8 @@ set(files
__threading_support
__tree
__tuple
+ __type_traits/integral_constant.h
+ __type_traits/is_callable.h
__undef_macros
__utility/as_const.h
__utility/auto_cast.h
diff --git a/libcxx/include/__type_traits/integral_constant.h b/libcxx/include/__type_traits/integral_constant.h
new file mode 100644
index 0000000000000..2449d1a906e84
--- /dev/null
+++ b/libcxx/include/__type_traits/integral_constant.h
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 _LIBCPP___TYPE_TRAITS_INTEGRAL_CONSTANT_H
+#define _LIBCPP___TYPE_TRAITS_INTEGRAL_CONSTANT_H
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Tp, _Tp __v>
+struct _LIBCPP_TEMPLATE_VIS integral_constant
+{
+ static _LIBCPP_CONSTEXPR const _Tp value = __v;
+ typedef _Tp value_type;
+ typedef integral_constant type;
+ _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_CONSTEXPR operator value_type() const _NOEXCEPT {return value;}
+#if _LIBCPP_STD_VER > 11
+ _LIBCPP_INLINE_VISIBILITY
+ constexpr value_type operator ()() const _NOEXCEPT {return value;}
+#endif
+};
+
+template <class _Tp, _Tp __v>
+_LIBCPP_CONSTEXPR const _Tp integral_constant<_Tp, __v>::value;
+
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+
+template <bool _Val>
+using _BoolConstant _LIBCPP_NODEBUG = integral_constant<bool, _Val>;
+
+#if _LIBCPP_STD_VER > 14
+template <bool __b>
+using bool_constant = integral_constant<bool, __b>;
+#endif
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___TYPE_TRAITS_INTEGRAL_CONSTANT_H
diff --git a/libcxx/include/__type_traits/is_callable.h b/libcxx/include/__type_traits/is_callable.h
new file mode 100644
index 0000000000000..73f894dce94c3
--- /dev/null
+++ b/libcxx/include/__type_traits/is_callable.h
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 _LIBCPP___TYPE_TRAITS_IS_CALLABLE_H
+#define _LIBCPP___TYPE_TRAITS_IS_CALLABLE_H
+
+#include <__config>
+#include <__type_traits/integral_constant.h>
+#include <__utility/declval.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template<class _Func, class... _Args, class = decltype(std::declval<_Func>()(std::declval<_Args>()...))>
+true_type __is_callable_helper(int);
+template<class...>
+false_type __is_callable_helper(...);
+
+template<class _Func, class... _Args>
+struct __is_callable : decltype(__is_callable_helper<_Func, _Args...>(0)) {};
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___TYPE_TRAITS_IS_CALLABLE_H
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index cf74a07e4be7c..0f07fd1577ea2 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -956,6 +956,9 @@ module std [system] {
header "type_traits"
export functional.__functional.unwrap_ref
export *
+
+ module integral_constant { private header "__type_traits/integral_constant.h" }
+ module is_callable { private header "__type_traits/is_callable.h" }
}
module typeindex {
header "typeindex"
diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index 2ea883fdbec03..4f00e909c3c21 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -419,6 +419,9 @@ namespace std
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
+#include <__type_traits/integral_constant.h>
+#include <__type_traits/is_callable.h>
+#include <__utility/declval.h>
#include <cstddef>
#include <version>
@@ -432,28 +435,6 @@ template <class _T1, class _T2> struct _LIBCPP_TEMPLATE_VIS pair;
template <class _Tp> class _LIBCPP_TEMPLATE_VIS reference_wrapper;
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS hash;
-template <class _Tp, _Tp __v>
-struct _LIBCPP_TEMPLATE_VIS integral_constant
-{
- static _LIBCPP_CONSTEXPR const _Tp value = __v;
- typedef _Tp value_type;
- typedef integral_constant type;
- _LIBCPP_INLINE_VISIBILITY
- _LIBCPP_CONSTEXPR operator value_type() const _NOEXCEPT {return value;}
-#if _LIBCPP_STD_VER > 11
- _LIBCPP_INLINE_VISIBILITY
- constexpr value_type operator ()() const _NOEXCEPT {return value;}
-#endif
-};
-
-template <class _Tp, _Tp __v>
-_LIBCPP_CONSTEXPR const _Tp integral_constant<_Tp, __v>::value;
-
-#if _LIBCPP_STD_VER > 14
-template <bool __b>
-using bool_constant = integral_constant<bool, __b>;
-#endif
-
template <bool, class _Tp = void> struct _LIBCPP_TEMPLATE_VIS enable_if {};
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS enable_if<true, _Tp> {typedef _Tp type;};
@@ -463,12 +444,6 @@ template <bool _Bp, class _Tp = void> using __enable_if_t _LIBCPP_NODEBUG = type
template <bool _Bp, class _Tp = void> using enable_if_t = typename enable_if<_Bp, _Tp>::type;
#endif
-typedef integral_constant<bool, true> true_type;
-typedef integral_constant<bool, false> false_type;
-
-template <bool _Val>
-using _BoolConstant _LIBCPP_NODEBUG = integral_constant<bool, _Val>;
-
template <bool> struct _MetaBase;
template <>
struct _MetaBase<true> {
@@ -1258,17 +1233,6 @@ template <class _Tp> struct _LIBCPP_TEMPLATE_VIS add_rvalue_reference
template <class _Tp> using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type;
#endif
-// Suppress deprecation notice for volatile-qualified return type resulting
-// from volatile-qualified types _Tp.
-_LIBCPP_SUPPRESS_DEPRECATED_PUSH
-template <class _Tp> _Tp&& __declval(int);
-template <class _Tp> _Tp __declval(long);
-_LIBCPP_SUPPRESS_DEPRECATED_POP
-
-template <class _Tp>
-decltype(__declval<_Tp>(0))
-declval() _NOEXCEPT;
-
template <class _Tp>
struct __unconstref {
typedef _LIBCPP_NODEBUG typename remove_const<typename remove_reference<_Tp>::type>::type type;
diff --git a/libcxx/test/libcxx/private_headers.verify.cpp b/libcxx/test/libcxx/private_headers.verify.cpp
index f7117dda10b23..f1173ff2ca51a 100644
--- a/libcxx/test/libcxx/private_headers.verify.cpp
+++ b/libcxx/test/libcxx/private_headers.verify.cpp
@@ -421,6 +421,8 @@ END-SCRIPT
#include <__thread/poll_with_backoff.h> // expected-error@*:* {{use of private header from outside its module: '__thread/poll_with_backoff.h'}}
#include <__thread/timed_backoff_policy.h> // expected-error@*:* {{use of private header from outside its module: '__thread/timed_backoff_policy.h'}}
#include <__tuple> // expected-error@*:* {{use of private header from outside its module: '__tuple'}}
+#include <__type_traits/integral_constant.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/integral_constant.h'}}
+#include <__type_traits/is_callable.h> // expected-error@*:* {{use of private header from outside its module: '__type_traits/is_callable.h'}}
#include <__utility/as_const.h> // expected-error@*:* {{use of private header from outside its module: '__utility/as_const.h'}}
#include <__utility/auto_cast.h> // expected-error@*:* {{use of private header from outside its module: '__utility/auto_cast.h'}}
#include <__utility/cmp.h> // expected-error@*:* {{use of private header from outside its module: '__utility/cmp.h'}}
diff --git a/libcxx/test/libcxx/type_traits/is_callable.compile.pass.cpp b/libcxx/test/libcxx/type_traits/is_callable.compile.pass.cpp
new file mode 100644
index 0000000000000..f7f76bbe9bef0
--- /dev/null
+++ b/libcxx/test/libcxx/type_traits/is_callable.compile.pass.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include <type_traits>
+
+struct Functor {
+ void operator()();
+};
+
+int func();
+
+struct NotFunctor {
+ bool compare();
+};
+
+struct ArgumentFunctor {
+ bool operator()(int, int);
+};
+
+static_assert(std::__is_callable<Functor>::value, "");
+static_assert(std::__is_callable<decltype(func)>::value, "");
+static_assert(!std::__is_callable<NotFunctor>::value, "");
+static_assert(!std::__is_callable<NotFunctor,
+ decltype(&NotFunctor::compare)>::value, "");
+static_assert(std::__is_callable<ArgumentFunctor, int, int>::value, "");
+static_assert(!std::__is_callable<ArgumentFunctor, int>::value, "");
More information about the libcxx-commits
mailing list