forked from OSchip/llvm-project
[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
This commit is contained in:
parent
628fcfd520
commit
08920cc043
|
@ -411,6 +411,8 @@ set(files
|
||||||
__threading_support
|
__threading_support
|
||||||
__tree
|
__tree
|
||||||
__tuple
|
__tuple
|
||||||
|
__type_traits/integral_constant.h
|
||||||
|
__type_traits/is_callable.h
|
||||||
__undef_macros
|
__undef_macros
|
||||||
__utility/as_const.h
|
__utility/as_const.h
|
||||||
__utility/auto_cast.h
|
__utility/auto_cast.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
|
|
@ -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
|
|
@ -956,6 +956,9 @@ module std [system] {
|
||||||
header "type_traits"
|
header "type_traits"
|
||||||
export functional.__functional.unwrap_ref
|
export functional.__functional.unwrap_ref
|
||||||
export *
|
export *
|
||||||
|
|
||||||
|
module integral_constant { private header "__type_traits/integral_constant.h" }
|
||||||
|
module is_callable { private header "__type_traits/is_callable.h" }
|
||||||
}
|
}
|
||||||
module typeindex {
|
module typeindex {
|
||||||
header "typeindex"
|
header "typeindex"
|
||||||
|
|
|
@ -419,6 +419,9 @@ namespace std
|
||||||
|
|
||||||
#include <__assert> // all public C++ headers provide the assertion handler
|
#include <__assert> // all public C++ headers provide the assertion handler
|
||||||
#include <__config>
|
#include <__config>
|
||||||
|
#include <__type_traits/integral_constant.h>
|
||||||
|
#include <__type_traits/is_callable.h>
|
||||||
|
#include <__utility/declval.h>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <version>
|
#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> class _LIBCPP_TEMPLATE_VIS reference_wrapper;
|
||||||
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS hash;
|
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 <bool, class _Tp = void> struct _LIBCPP_TEMPLATE_VIS enable_if {};
|
||||||
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS enable_if<true, _Tp> {typedef _Tp type;};
|
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;
|
template <bool _Bp, class _Tp = void> using enable_if_t = typename enable_if<_Bp, _Tp>::type;
|
||||||
#endif
|
#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 <bool> struct _MetaBase;
|
||||||
template <>
|
template <>
|
||||||
struct _MetaBase<true> {
|
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;
|
template <class _Tp> using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type;
|
||||||
#endif
|
#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>
|
template <class _Tp>
|
||||||
struct __unconstref {
|
struct __unconstref {
|
||||||
typedef _LIBCPP_NODEBUG typename remove_const<typename remove_reference<_Tp>::type>::type type;
|
typedef _LIBCPP_NODEBUG typename remove_const<typename remove_reference<_Tp>::type>::type type;
|
||||||
|
|
|
@ -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/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 <__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 <__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/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/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'}}
|
#include <__utility/cmp.h> // expected-error@*:* {{use of private header from outside its module: '__utility/cmp.h'}}
|
||||||
|
|
|
@ -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, "");
|
Loading…
Reference in New Issue