1// -*- C++ -*- 2//===----------------------------------------------------------------------===// 3// 4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5// See https://llvm.org/LICENSE.txt for license information. 6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef _LIBCPP_EXPERIMENTAL_TYPE_TRAITS 11#define _LIBCPP_EXPERIMENTAL_TYPE_TRAITS 12 13/** 14 experimental/type_traits synopsis 15 16// C++1y 17#include <type_traits> 18 19namespace std { 20namespace experimental { 21inline namespace fundamentals_v1 { 22 23 // 3.3.2, Other type transformations 24 template <class> class invocation_type; // not defined 25 template <class F, class... ArgTypes> class invocation_type<F(ArgTypes...)>; 26 template <class> class raw_invocation_type; // not defined 27 template <class F, class... ArgTypes> class raw_invocation_type<F(ArgTypes...)>; 28 29 template <class T> 30 using invocation_type_t = typename invocation_type<T>::type; 31 template <class T> 32 using raw_invocation_type_t = typename raw_invocation_type<T>::type; 33 34 // 3.3.4, Detection idiom 35 template <class...> using void_t = void; 36 37 struct nonesuch { 38 nonesuch() = delete; 39 ~nonesuch() = delete; 40 nonesuch(nonesuch const&) = delete; 41 void operator=(nonesuch const&) = delete; 42 }; 43 44 template <template<class...> class Op, class... Args> 45 using is_detected = see below; 46 template <template<class...> class Op, class... Args> 47 constexpr bool is_detected_v = is_detected<Op, Args...>::value; 48 template <template<class...> class Op, class... Args> 49 using detected_t = see below; 50 template <class Default, template<class...> class Op, class... Args> 51 using detected_or = see below; 52 template <class Default, template<class...> class Op, class... Args> 53 using detected_or_t = typename detected_or<Default, Op, Args...>::type; 54 template <class Expected, template<class...> class Op, class... Args> 55 using is_detected_exact = is_same<Expected, detected_t<Op, Args...>>; 56 template <class Expected, template<class...> class Op, class... Args> 57 constexpr bool is_detected_exact_v 58 = is_detected_exact<Expected, Op, Args...>::value; 59 template <class To, template<class...> class Op, class... Args> 60 using is_detected_convertible = is_convertible<detected_t<Op, Args...>, To>; 61 template <class To, template<class...> class Op, class... Args> 62 constexpr bool is_detected_convertible_v 63 = is_detected_convertible<To, Op, Args...>::value; 64 65} // namespace fundamentals_v1 66} // namespace experimental 67} // namespace std 68 69 */ 70 71#include <__assert> // all public C++ headers provide the assertion handler 72#include <experimental/__config> 73 74#if _LIBCPP_STD_VER > 11 75 76#include <initializer_list> 77#include <type_traits> 78 79#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 80# pragma GCC system_header 81#endif 82 83_LIBCPP_BEGIN_NAMESPACE_LFTS 84 85// 3.3.2, Other type transformations 86/* 87template <class> 88class _LIBCPP_TEMPLATE_VIS raw_invocation_type; 89 90template <class _Fn, class ..._Args> 91class _LIBCPP_TEMPLATE_VIS raw_invocation_type<_Fn(_Args...)>; 92 93template <class> 94class _LIBCPP_TEMPLATE_VIS invokation_type; 95 96template <class _Fn, class ..._Args> 97class _LIBCPP_TEMPLATE_VIS invokation_type<_Fn(_Args...)>; 98 99template <class _Tp> 100using invokation_type_t = typename invokation_type<_Tp>::type; 101 102template <class _Tp> 103using raw_invocation_type_t = typename raw_invocation_type<_Tp>::type; 104*/ 105 106// 3.3.4, Detection idiom 107template <class...> using void_t = void; 108 109struct nonesuch : private __nat { // make nonesuch "not an aggregate" 110 ~nonesuch() = delete; 111 nonesuch (nonesuch const&) = delete; 112 void operator=(nonesuch const&) = delete; 113 }; 114 115template <class _Default, class _AlwaysVoid, template <class...> class _Op, class... _Args> 116struct _DETECTOR { 117 using value_t = false_type; 118 using type = _Default; 119 }; 120 121template <class _Default, template <class...> class _Op, class... _Args> 122struct _DETECTOR<_Default, void_t<_Op<_Args...>>, _Op, _Args...> { 123 using value_t = true_type; 124 using type = _Op<_Args...>; 125 }; 126 127 128template <template<class...> class _Op, class... _Args> 129 using is_detected = typename _DETECTOR<nonesuch, void, _Op, _Args...>::value_t; 130template <template<class...> class _Op, class... _Args> 131 using detected_t = typename _DETECTOR<nonesuch, void, _Op, _Args...>::type; 132template <template<class...> class _Op, class... _Args> 133 _LIBCPP_CONSTEXPR bool is_detected_v = is_detected<_Op, _Args...>::value; 134 135template <class Default, template<class...> class _Op, class... _Args> 136 using detected_or = _DETECTOR<Default, void, _Op, _Args...>; 137template <class Default, template<class...> class _Op, class... _Args> 138 using detected_or_t = typename detected_or<Default, _Op, _Args...>::type; 139 140template <class Expected, template<class...> class _Op, class... _Args> 141 using is_detected_exact = is_same<Expected, detected_t<_Op, _Args...>>; 142template <class Expected, template<class...> class _Op, class... _Args> 143 _LIBCPP_CONSTEXPR bool is_detected_exact_v = is_detected_exact<Expected, _Op, _Args...>::value; 144 145template <class To, template<class...> class _Op, class... _Args> 146 using is_detected_convertible = is_convertible<detected_t<_Op, _Args...>, To>; 147template <class To, template<class...> class _Op, class... _Args> 148 _LIBCPP_CONSTEXPR bool is_detected_convertible_v = is_detected_convertible<To, _Op, _Args...>::value; 149 150 151_LIBCPP_END_NAMESPACE_LFTS 152 153#endif /* _LIBCPP_STD_VER > 11 */ 154 155#endif /* _LIBCPP_EXPERIMENTAL_TYPE_TRAITS */ 156