traits.h 5.2 KB

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