File: //usr/include/hphp/util/type-traits.h
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_UTIL_TYPE_TRAITS_H_
#define incl_HPHP_UTIL_TYPE_TRAITS_H_
#include <type_traits>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
/*
* Is `T' the same type as `U' or any type in `Tail...'?
*/
template<class T, class U, class... Tail> struct is_any;
template<class T, class U>
struct is_any<T,U> : std::is_same<T,U> {};
template<class T, class U, class V, class... Tail>
struct is_any<T,U,V,Tail...> : std::integral_constant<
bool,
std::is_same<T,U>::value || is_any<T,V,Tail...>::value
> {};
///////////////////////////////////////////////////////////////////////////////
/*
* Whether `T' and `U' are the same type, with the outermost const-qualifier
* stripped away.
*/
template<class T, class U>
using is_same_upto_const = std::is_same<
typename std::remove_const<T>::type,
typename std::remove_const<U>::type
>;
namespace detail {
template<class... Ts> struct maybe_const_pred;
template<>
struct maybe_const_pred<> : std::true_type {};
template<class T>
struct maybe_const_pred<T> : std::true_type {};
template<class T, class U, class... Tail>
struct maybe_const_pred<T, U, Tail...> : std::integral_constant<
bool,
is_same_upto_const<T,U>::value &&
maybe_const_pred<Tail...>::value
> {};
template<class... Ts> struct maybe_const_result;
template<>
struct maybe_const_result<> { using type = void; };
template<class R>
struct maybe_const_result<R> { using type = R; };
template<class T, class U, class... Tail>
struct maybe_const_result<T, U, Tail...> : maybe_const_result<Tail...> {};
}
/*
* Pattern for templatizing functions to take an optionally-const argument.
* Writing
*
* template<class T1, class T2, ...>
* maybe_const<T1, K1, T2, K2, ..., R>::type
*
* is equivalent to
*
* template<class T1, class T2, ...>
* std::enable_if<
* is_same_upto_const<T1, K1>::value &&
* is_same_upto_const<T2, K2>::value &&
* ...,
* R
* >::type
*/
template<class T, class K, class... Tail>
using maybe_const = std::enable_if<
detail::maybe_const_pred<T, K, Tail...>::value,
typename detail::maybe_const_result<T, K, Tail...>::type
>;
///////////////////////////////////////////////////////////////////////////////
}
#endif