Templates.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. ///
  2. /// \file Util/Templates.hpp
  3. ///
  4. /// Utility templates and metaprograming classes.
  5. ///
  6. /// \copyright
  7. /// Copyright (c) 2017-2017 Josh Blum
  8. /// 2020 Nicholas Corgan
  9. /// SPDX-License-Identifier: BSL-1.0
  10. ///
  11. #pragma once
  12. #include <Pothos/Config.hpp>
  13. #include <complex> // std::complex
  14. #include <type_traits> //std::decay
  15. #include <functional> //std::reference_wrapper
  16. namespace Pothos {
  17. namespace Util {
  18. /*!*********************************************************************
  19. * \defgroup unwrapref Implementation for unwrap_refwrapper and special_decay_t
  20. * special_decay_t = decay + unwrapping a reference wrapper
  21. * \see http://en.cppreference.com/w/cpp/utility/tuple/make_tuple
  22. * \{
  23. **********************************************************************/
  24. /*!
  25. * Template base implementation to extract the type of non-reference wrappers
  26. * \tparam T the input type to the template
  27. */
  28. template <typename T>
  29. struct unwrap_refwrapper
  30. {
  31. using type = T; //!< the input type of non-reference wrappers
  32. };
  33. /*!
  34. * Template specialization to extract the type held within a reference wrapper
  35. * \tparam T the input type to the template
  36. */
  37. template <typename T>
  38. struct unwrap_refwrapper<std::reference_wrapper<T>>
  39. {
  40. using type = T&; //!< the type held within a reference wrapper
  41. };
  42. /*!
  43. * Strip const and reference from a type, and remove optional reference wrapper.
  44. * \tparam T the input type to the template
  45. */
  46. template <typename T>
  47. using special_decay_t = typename unwrap_refwrapper<typename std::decay<T>::type>::type;
  48. //! \}
  49. /*!*********************************************************************
  50. * \defgroup intseq Integer sequence implementation for C++11
  51. * This can be removed when C++14 is required.
  52. * \see http://en.cppreference.com/w/cpp/utility/integer_sequence
  53. * \{
  54. **********************************************************************/
  55. /*!
  56. * A parameter pack of incrementing numbers 0 to N-1
  57. * \tparam T the integer type
  58. * \tparam Ints the parameter pack of integers
  59. */
  60. template<typename T, T... Ints>
  61. struct integer_sequence
  62. {
  63. typedef T value_type; //!< The type of each integer
  64. //! The size of the integer pack
  65. static constexpr std::size_t size(void) noexcept
  66. {
  67. return sizeof...(Ints);
  68. }
  69. };
  70. //! \cond
  71. template<typename T, int N, T... Ints>
  72. struct GenSeq : GenSeq<T, N-1, T(N-1), Ints...> {};
  73. template<typename T, T... Ints>
  74. struct GenSeq<T, 0, Ints...>
  75. {
  76. typedef integer_sequence<T, Ints...> Type;
  77. };
  78. //! \endcond
  79. /*!
  80. * Specialize the integer sequence for size_t
  81. * \tparam Ints the parameter pack of integers
  82. */
  83. template<std::size_t... Ints>
  84. using index_sequence = integer_sequence<std::size_t, Ints...>;
  85. /*!
  86. * Make an integer sequence from the length
  87. * \tparam T the integer type
  88. * \tparam N the length
  89. */
  90. template<typename T, T N>
  91. using make_integer_sequence = typename GenSeq<T, int(N)>::Type;
  92. /*!
  93. * Make an index sequence from the length
  94. * \tparam N the length
  95. */
  96. template<std::size_t N>
  97. using make_index_sequence = make_integer_sequence<std::size_t, N>;
  98. /*!
  99. * Make an index sequence from a parameter pack
  100. * \tparam T the parameter pack
  101. */
  102. template<typename... T>
  103. using index_sequence_for = make_index_sequence<sizeof...(T)>;
  104. //! \}
  105. /*!*********************************************************************
  106. * Disable SFINAE type used with universal reference constructors
  107. * \see http://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/
  108. **********************************************************************/
  109. template<typename BaseType, typename OtherType>
  110. using disable_if_same = typename std::enable_if<
  111. not std::is_same<BaseType, typename std::decay<OtherType>::type>::value>::type;
  112. /*!*********************************************************************
  113. * \defgroup complexsfinae Use when functions require different behaviors
  114. * for scalar vs. complex types.
  115. * \{
  116. **********************************************************************/
  117. template <typename T>
  118. struct is_complex: std::false_type {};
  119. template <typename T>
  120. struct is_complex<std::complex<T>>: std::true_type {};
  121. template <typename T, typename ReturnType>
  122. using disable_if_complex = typename std::enable_if<
  123. not is_complex<typename std::decay<T>::type>::value,
  124. ReturnType>::type;
  125. template <typename T, typename ReturnType>
  126. using enable_if_complex = typename std::enable_if<
  127. is_complex<typename std::decay<T>::type>::value,
  128. ReturnType>::type;
  129. //! \}
  130. } //namespace Util
  131. } //namespace Pothos