[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