Micro template library A library for building device drivers
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 

172 lignes
5.5 KiB

  1. /*!
  2. * \file detection.h
  3. * \brief Detection idiom based on WG21's N4502[1] from Walter E. Brown
  4. *
  5. * [1]: www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4502.pdf
  6. *
  7. * Copyright (C) 2018-2019 Christos Choutouridis
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU Lesser General Public License as
  11. * published by the Free Software Foundation, either version 3
  12. * of the License, or (at your option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public License
  20. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  21. */
  22. #ifndef __utl_meta_detection_h__
  23. #define __utl_meta_detection_h__
  24. #include <utl/core/impl.h>
  25. #include <utl/meta/logical.h>
  26. #include <type_traits>
  27. /*!
  28. * \ingroup meta
  29. * \defgroup detection
  30. * Detection idiom support header.
  31. */
  32. //! @{
  33. namespace utl {
  34. namespace meta {
  35. /*!
  36. * void_t meta-function that maps a sequence of any types to the type void
  37. */
  38. //! @{
  39. #if defined(UTL_WORKAROUND_CWG_1558)
  40. template<typename... _Ts>
  41. struct void_ {
  42. using type = void;
  43. };
  44. //! void_t type alias
  45. template<typename... _Ts>
  46. using void_t = eval<void_<_Ts...>>;
  47. #else
  48. //! void_ type alias
  49. template <typename...> using void_ = void;
  50. //! void_t type alias
  51. template <typename...> using void_t = void;
  52. #endif
  53. //! @}
  54. /*!
  55. * Not a type to use in detected idiom
  56. */
  57. struct nat_ {
  58. nat_() = delete;
  59. ~nat_() = delete;
  60. nat_(nat_ const&) = delete;
  61. void operator = (nat_ const&) = delete;
  62. };
  63. //! Detector for detection idiom
  64. //! @{
  65. namespace detail {
  66. template <typename Default,
  67. typename AlwaysVoid,
  68. template<typename...> class Op, typename... Args>
  69. struct detector {
  70. using detected = false_;
  71. using type = Default;
  72. };
  73. template <typename Default,
  74. template<typename...> class Op, typename... Args>
  75. struct detector <Default, void_t<Op<Args...>>, Op, Args...> {
  76. using detected = true_;
  77. using type = Op<Args...>;
  78. };
  79. //! helper for detected_or_t
  80. template <typename Default,
  81. template<typename...> class Op, typename... Args>
  82. using detected_or = detector<Default, void, Op, Args...>;
  83. } // namespace detail
  84. //! @}
  85. /*!
  86. * detection interface
  87. */
  88. //! @{
  89. /*!
  90. * Checks if Op<Args...> is a valid expression without evaluating it.
  91. *
  92. * \param Op a meta-callback function to pass Args...
  93. * \param Args... types to pass to Op for checking
  94. * \return status of the operation [bool_]
  95. * \arg true_ if Op<Args...> is valid expression
  96. * \arg false_ if Op<Args...> is not valid
  97. *
  98. * \example
  99. * \code
  100. * // archetypal alias for a copy assignment operation
  101. * template< class T >
  102. * using copy_assign_t = decltype( declval<T&>() = declval<T const &>() );
  103. *
  104. * template< class T >
  105. * using is_copy_assignable = is_detected< T, copy_assign_t >;
  106. * \endcode
  107. */
  108. template <template<typename...> class Op, typename... Args>
  109. using is_detected = typename detail::detector<nat_, void, Op, Args...>::detected;
  110. //! Detection predicate
  111. template< template<typename...> class Op, typename... Args>
  112. constexpr bool is_detected_v = is_detected<Op, Args...>::value;
  113. //! @}
  114. /*!
  115. * Detection idiom toolkit
  116. */
  117. //! @{
  118. //! evaluates to evaluation of Op<Args...> if it's valid and to nat_ if not
  119. template <template<typename...> class Op, typename... Args>
  120. using detected_t = eval <
  121. detail::detector<nat_, void, Op, Args...>
  122. >;
  123. //! evaluates to evaluation of Op<Args...> if it's valid and to \p Default if not
  124. template <typename Default,
  125. template<typename...> class Op, typename... Args>
  126. using detected_or_t = eval <
  127. detail::detected_or<Default, Op, Args...>
  128. >;
  129. //! evaluates to true_ if evaluation of Op<Args...> is \p Expected and to false_ if not
  130. template <typename Expected,
  131. template<typename...> class Op, typename... Args >
  132. using is_detected_exact = same_<Expected, detected_t<Op, Args...> >;
  133. //! evaluates to true if evaluation of Op<Args...> is \p Expected and to false if not
  134. template <typename Expected,
  135. template<typename...> class Op, typename... Args >
  136. constexpr bool is_detected_exact_v = is_detected_exact< Expected, Op, Args...>::value;
  137. //! evaluates to true_ if evaluation of Op<Args...> is convertible to \p To
  138. //! and to false_ if not
  139. template <typename To,
  140. template<typename...> class Op, typename... Args >
  141. using is_detected_convertible = std::is_convertible< detected_t<Op, Args...>, To >;
  142. //! evaluates to true if evaluation of Op<Args...> is convertible to \p To
  143. //! and to false if not
  144. template <typename To,
  145. template<typename...> class Op, typename... Args >
  146. constexpr bool is_detected_convertible_v =
  147. is_detected_convertible<To, Op, Args...>::value;
  148. //! @}
  149. }}
  150. //!@}
  151. #endif /* __utl_meta_detection_h__ */