2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_UTIL_TYPE_TRAITS_H_
18 #define incl_HPHP_UTIL_TYPE_TRAITS_H_
20 #include <type_traits>
25 ///////////////////////////////////////////////////////////////////////////////
28 constexpr auto identity(T
&& t
) noexcept
-> decltype(std::forward
<T
>(t
)) {
29 return std::forward
<T
>(t
);
32 ///////////////////////////////////////////////////////////////////////////////
35 * Is `T' the same type as `U' or any type in `Tail...'?
37 template<class T
, class U
, class... Tail
> struct is_any
;
39 template<class T
, class U
>
40 struct is_any
<T
,U
> : std::is_same
<T
,U
> {};
42 template<class T
, class U
, class V
, class... Tail
>
43 struct is_any
<T
,U
,V
,Tail
...> : std::integral_constant
<
45 std::is_same
<T
,U
>::value
|| is_any
<T
,V
,Tail
...>::value
48 ///////////////////////////////////////////////////////////////////////////////
53 template<typename T
> struct ident
{ using type
= T
; };
54 template<typename T
> using ident_t
= typename ident
<T
>::type
;
57 * Stateless tuple for parameter unpacking.
59 template<typename
...> struct pack
{};
62 * Clone of std::conjunction<>.
64 template<class...> struct conjunction
: std::true_type
{ };
65 template<class B1
> struct conjunction
<B1
> : B1
{ };
66 template<class B1
, class... Bn
>
67 struct conjunction
<B1
, Bn
...>
68 : std::conditional_t
<bool(B1::value
), conjunction
<Bn
...>, B1
> {};
71 * Clone of std::disjunction<>.
73 template<class...> struct disjunction
: std::false_type
{ };
74 template<class B1
> struct disjunction
<B1
> : B1
{ };
75 template<class B1
, class... Bn
>
76 struct disjunction
<B1
, Bn
...>
77 : std::conditional_t
<bool(B1::value
), B1
, disjunction
<Bn
...>> {};
80 * Helper for appending a type parameter to a template class's variadic
83 template<typename Head
, typename Tail
> struct cons
;
84 template<template<typename
...> class List
, typename T
, typename
... Args
>
85 struct cons
<T
, List
<Args
...>> {
86 using type
= List
<T
, Args
...>;
89 ///////////////////////////////////////////////////////////////////////////////
92 * Whether `T' and `U' are the same type, with the outermost const-qualifier
95 template<class T
, class U
>
96 using is_same_upto_const
= std::is_same
<
97 typename
std::remove_const
<T
>::type
,
98 typename
std::remove_const
<U
>::type
103 template<class... Ts
> struct maybe_const_pred
;
106 struct maybe_const_pred
<> : std::true_type
{};
109 struct maybe_const_pred
<T
> : std::true_type
{};
111 template<class T
, class U
, class... Tail
>
112 struct maybe_const_pred
<T
, U
, Tail
...> : std::integral_constant
<
114 is_same_upto_const
<T
,U
>::value
&&
115 maybe_const_pred
<Tail
...>::value
118 template<class... Ts
> struct maybe_const_result
;
121 struct maybe_const_result
<> { using type
= void; };
124 struct maybe_const_result
<R
> { using type
= R
; };
126 template<class T
, class U
, class... Tail
>
127 struct maybe_const_result
<T
, U
, Tail
...> : maybe_const_result
<Tail
...> {};
132 * Pattern for templatizing functions to take an optionally-const argument.
135 * template<class T1, class T2, ...>
136 * maybe_const<T1, K1, T2, K2, ..., R>::type
140 * template<class T1, class T2, ...>
142 * is_same_upto_const<T1, K1>::value &&
143 * is_same_upto_const<T2, K2>::value &&
148 template<class T
, class K
, class... Tail
>
149 using maybe_const
= std::enable_if
<
150 detail::maybe_const_pred
<T
, K
, Tail
...>::value
,
151 typename
detail::maybe_const_result
<T
, K
, Tail
...>::type
154 template <typename Fn
, typename
... Args
>
155 struct is_invocable
: public std::is_constructible
<
156 std::function
<void(Args
...)>, Fn
&&
159 ///////////////////////////////////////////////////////////////////////////////