1 /* Copyright (C) 2017-2023 Free Software Foundation, Inc. 2 3 This file is part of GDB. 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18 #ifndef COMMON_TRAITS_H 19 #define COMMON_TRAITS_H 20 21 #include <type_traits> 22 23 /* GCC does not understand __has_feature. */ 24 #if !defined(__has_feature) 25 # define __has_feature(x) 0 26 #endif 27 28 /* HAVE_IS_TRIVIALLY_COPYABLE is defined as 1 iff 29 std::is_trivially_copyable is available. GCC only implemented it 30 in GCC 5. */ 31 #if (__has_feature(is_trivially_copyable) \ 32 || (defined __GNUC__ && __GNUC__ >= 5)) 33 # define HAVE_IS_TRIVIALLY_COPYABLE 1 34 #endif 35 36 /* HAVE_IS_TRIVIALLY_CONSTRUCTIBLE is defined as 1 iff 37 std::is_trivially_constructible is available. GCC only implemented it 38 in GCC 5. */ 39 #if (__has_feature(is_trivially_constructible) \ 40 || (defined __GNUC__ && __GNUC__ >= 5)) 41 # define HAVE_IS_TRIVIALLY_CONSTRUCTIBLE 1 42 #endif 43 44 namespace gdb { 45 46 /* Pre C++14-safe (CWG 1558) version of C++17's std::void_t. See 47 <http://en.cppreference.com/w/cpp/types/void_t>. */ 48 49 template<typename... Ts> 50 struct make_void { typedef void type; }; 51 52 template<typename... Ts> 53 using void_t = typename make_void<Ts...>::type; 54 55 /* Implementation of the detection idiom: 56 57 - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4502.pdf 58 - http://en.cppreference.com/w/cpp/experimental/is_detected 59 60 */ 61 62 struct nonesuch 63 { 64 nonesuch () = delete; 65 ~nonesuch () = delete; 66 nonesuch (const nonesuch &) = delete; 67 void operator= (const nonesuch &) = delete; 68 }; 69 70 namespace detection_detail { 71 /* Implementation of the detection idiom (negative case). */ 72 template<typename Default, typename AlwaysVoid, 73 template<typename...> class Op, typename... Args> 74 struct detector 75 { 76 using value_t = std::false_type; 77 using type = Default; 78 }; 79 80 /* Implementation of the detection idiom (positive case). */ 81 template<typename Default, template<typename...> class Op, typename... Args> 82 struct detector<Default, void_t<Op<Args...>>, Op, Args...> 83 { 84 using value_t = std::true_type; 85 using type = Op<Args...>; 86 }; 87 88 /* Detect whether Op<Args...> is a valid type, use Default if not. */ 89 template<typename Default, template<typename...> class Op, 90 typename... Args> 91 using detected_or = detector<Default, void, Op, Args...>; 92 93 /* Op<Args...> if that is a valid type, otherwise Default. */ 94 template<typename Default, template<typename...> class Op, 95 typename... Args> 96 using detected_or_t 97 = typename detected_or<Default, Op, Args...>::type; 98 99 } /* detection_detail */ 100 101 template<template<typename...> class Op, typename... Args> 102 using is_detected 103 = typename detection_detail::detector<nonesuch, void, Op, Args...>::value_t; 104 105 template<template<typename...> class Op, typename... Args> 106 using detected_t 107 = typename detection_detail::detector<nonesuch, void, Op, Args...>::type; 108 109 template<typename Default, template<typename...> class Op, typename... Args> 110 using detected_or = detection_detail::detected_or<Default, Op, Args...>; 111 112 template<typename Default, template<typename...> class Op, typename... Args> 113 using detected_or_t = typename detected_or<Default, Op, Args...>::type; 114 115 template<typename Expected, template<typename...> class Op, typename... Args> 116 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>; 117 118 template<typename To, template<typename...> class Op, typename... Args> 119 using is_detected_convertible 120 = std::is_convertible<detected_t<Op, Args...>, To>; 121 122 /* A few trait helpers, mainly stolen from libstdc++. Uppercase 123 because "and/or", etc. are reserved keywords. */ 124 125 template<typename Predicate> 126 struct Not : public std::integral_constant<bool, !Predicate::value> 127 {}; 128 129 template<typename...> 130 struct Or; 131 132 template<> 133 struct Or<> : public std::false_type 134 {}; 135 136 template<typename B1> 137 struct Or<B1> : public B1 138 {}; 139 140 template<typename B1, typename B2> 141 struct Or<B1, B2> 142 : public std::conditional<B1::value, B1, B2>::type 143 {}; 144 145 template<typename B1,typename B2,typename B3, typename... Bn> 146 struct Or<B1, B2, B3, Bn...> 147 : public std::conditional<B1::value, B1, Or<B2, B3, Bn...>>::type 148 {}; 149 150 template<typename...> 151 struct And; 152 153 template<> 154 struct And<> : public std::true_type 155 {}; 156 157 template<typename B1> 158 struct And<B1> : public B1 159 {}; 160 161 template<typename B1, typename B2> 162 struct And<B1, B2> 163 : public std::conditional<B1::value, B2, B1>::type 164 {}; 165 166 template<typename B1, typename B2, typename B3, typename... Bn> 167 struct And<B1, B2, B3, Bn...> 168 : public std::conditional<B1::value, And<B2, B3, Bn...>, B1>::type 169 {}; 170 171 /* Concepts-light-like helper to make SFINAE logic easier to read. */ 172 template<typename Condition> 173 using Requires = typename std::enable_if<Condition::value, void>::type; 174 } 175 176 #endif /* COMMON_TRAITS_H */ 177