1 /* Copyright (C) 2017-2024 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 namespace gdb { 24 25 /* Implementation of the detection idiom: 26 27 - http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4502.pdf 28 - http://en.cppreference.com/w/cpp/experimental/is_detected 29 30 */ 31 32 struct nonesuch 33 { 34 nonesuch () = delete; 35 ~nonesuch () = delete; 36 nonesuch (const nonesuch &) = delete; 37 void operator= (const nonesuch &) = delete; 38 }; 39 40 namespace detection_detail { 41 /* Implementation of the detection idiom (negative case). */ 42 template<typename Default, typename AlwaysVoid, 43 template<typename...> class Op, typename... Args> 44 struct detector 45 { 46 using value_t = std::false_type; 47 using type = Default; 48 }; 49 50 /* Implementation of the detection idiom (positive case). */ 51 template<typename Default, template<typename...> class Op, typename... Args> 52 struct detector<Default, std::void_t<Op<Args...>>, Op, Args...> 53 { 54 using value_t = std::true_type; 55 using type = Op<Args...>; 56 }; 57 58 /* Detect whether Op<Args...> is a valid type, use Default if not. */ 59 template<typename Default, template<typename...> class Op, 60 typename... Args> 61 using detected_or = detector<Default, void, Op, Args...>; 62 63 /* Op<Args...> if that is a valid type, otherwise Default. */ 64 template<typename Default, template<typename...> class Op, 65 typename... Args> 66 using detected_or_t 67 = typename detected_or<Default, Op, Args...>::type; 68 69 } /* detection_detail */ 70 71 template<template<typename...> class Op, typename... Args> 72 using is_detected 73 = typename detection_detail::detector<nonesuch, void, Op, Args...>::value_t; 74 75 template<template<typename...> class Op, typename... Args> 76 using detected_t 77 = typename detection_detail::detector<nonesuch, void, Op, Args...>::type; 78 79 template<typename Default, template<typename...> class Op, typename... Args> 80 using detected_or = detection_detail::detected_or<Default, Op, Args...>; 81 82 template<typename Default, template<typename...> class Op, typename... Args> 83 using detected_or_t = typename detected_or<Default, Op, Args...>::type; 84 85 template<typename Expected, template<typename...> class Op, typename... Args> 86 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>; 87 88 template<typename To, template<typename...> class Op, typename... Args> 89 using is_detected_convertible 90 = std::is_convertible<detected_t<Op, Args...>, To>; 91 92 /* A few trait helpers, mainly stolen from libstdc++. Uppercase 93 because "and/or", etc. are reserved keywords. */ 94 95 template<typename Predicate> 96 struct Not : public std::integral_constant<bool, !Predicate::value> 97 {}; 98 99 template<typename...> 100 struct Or; 101 102 template<> 103 struct Or<> : public std::false_type 104 {}; 105 106 template<typename B1> 107 struct Or<B1> : public B1 108 {}; 109 110 template<typename B1, typename B2> 111 struct Or<B1, B2> 112 : public std::conditional<B1::value, B1, B2>::type 113 {}; 114 115 template<typename B1,typename B2,typename B3, typename... Bn> 116 struct Or<B1, B2, B3, Bn...> 117 : public std::conditional<B1::value, B1, Or<B2, B3, Bn...>>::type 118 {}; 119 120 template<typename...> 121 struct And; 122 123 template<> 124 struct And<> : public std::true_type 125 {}; 126 127 template<typename B1> 128 struct And<B1> : public B1 129 {}; 130 131 template<typename B1, typename B2> 132 struct And<B1, B2> 133 : public std::conditional<B1::value, B2, B1>::type 134 {}; 135 136 template<typename B1, typename B2, typename B3, typename... Bn> 137 struct And<B1, B2, B3, Bn...> 138 : public std::conditional<B1::value, And<B2, B3, Bn...>, B1>::type 139 {}; 140 141 /* Concepts-light-like helper to make SFINAE logic easier to read. */ 142 template<typename Condition> 143 using Requires = typename std::enable_if<Condition::value, void>::type; 144 } 145 146 template<typename T> 147 using RequireLongest = gdb::Requires<gdb::Or<std::is_same<T, LONGEST>, 148 std::is_same<T, ULONGEST>>>; 149 150 #endif /* COMMON_TRAITS_H */ 151