diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -411,6 +411,8 @@ __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 --- /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 +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 +_LIBCPP_CONSTEXPR const _Tp integral_constant<_Tp, __v>::value; + +typedef integral_constant true_type; +typedef integral_constant false_type; + +template +using _BoolConstant _LIBCPP_NODEBUG = integral_constant; + +#if _LIBCPP_STD_VER > 14 +template +using bool_constant = integral_constant; +#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 --- /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()(std::declval<_Args>()...))> +true_type __is_callable_helper(int); +template +false_type __is_callable_helper(...); + +template +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 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -956,6 +956,9 @@ 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 --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -419,6 +419,9 @@ #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 #include @@ -432,28 +435,6 @@ template class _LIBCPP_TEMPLATE_VIS reference_wrapper; template struct _LIBCPP_TEMPLATE_VIS hash; -template -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 -_LIBCPP_CONSTEXPR const _Tp integral_constant<_Tp, __v>::value; - -#if _LIBCPP_STD_VER > 14 -template -using bool_constant = integral_constant; -#endif - template struct _LIBCPP_TEMPLATE_VIS enable_if {}; template struct _LIBCPP_TEMPLATE_VIS enable_if {typedef _Tp type;}; @@ -463,12 +444,6 @@ template using enable_if_t = typename enable_if<_Bp, _Tp>::type; #endif -typedef integral_constant true_type; -typedef integral_constant false_type; - -template -using _BoolConstant _LIBCPP_NODEBUG = integral_constant; - template struct _MetaBase; template <> struct _MetaBase { @@ -1258,17 +1233,6 @@ template 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 _Tp&& __declval(int); -template _Tp __declval(long); -_LIBCPP_SUPPRESS_DEPRECATED_POP - -template -decltype(__declval<_Tp>(0)) -declval() _NOEXCEPT; - template struct __unconstref { typedef _LIBCPP_NODEBUG typename remove_const::type>::type type; diff --git a/libcxx/test/libcxx/private_headers.verify.cpp b/libcxx/test/libcxx/private_headers.verify.cpp --- a/libcxx/test/libcxx/private_headers.verify.cpp +++ b/libcxx/test/libcxx/private_headers.verify.cpp @@ -421,6 +421,8 @@ #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 --- /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 + +struct Functor { + void operator()(); +}; + +int func(); + +struct NotFunctor { + bool compare(); +}; + +struct ArgumentFunctor { + bool operator()(int, int); +}; + +static_assert(std::__is_callable::value, ""); +static_assert(std::__is_callable::value, ""); +static_assert(!std::__is_callable::value, ""); +static_assert(!std::__is_callable::value, ""); +static_assert(std::__is_callable::value, ""); +static_assert(!std::__is_callable::value, "");