2
0

tuple.hpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. #ifndef ENTT_CORE_TUPLE_HPP
  2. #define ENTT_CORE_TUPLE_HPP
  3. #include <tuple>
  4. #include <type_traits>
  5. #include <utility>
  6. namespace entt {
  7. /**
  8. * @cond TURN_OFF_DOXYGEN
  9. * Internal details not to be documented.
  10. */
  11. namespace internal {
  12. template<typename>
  13. struct is_tuple_impl: std::false_type {};
  14. template<typename... Args>
  15. struct is_tuple_impl<std::tuple<Args...>>: std::true_type {};
  16. } // namespace internal
  17. /**
  18. * Internal details not to be documented.
  19. * @endcond
  20. */
  21. /**
  22. * @brief Provides the member constant `value` to true if a given type is a
  23. * tuple, false otherwise.
  24. * @tparam Type The type to test.
  25. */
  26. template<typename Type>
  27. struct is_tuple: internal::is_tuple_impl<std::remove_cv_t<Type>> {};
  28. /**
  29. * @brief Helper variable template.
  30. * @tparam Type The type to test.
  31. */
  32. template<typename Type>
  33. inline constexpr bool is_tuple_v = is_tuple<Type>::value;
  34. /**
  35. * @brief Utility function to unwrap tuples of a single element.
  36. * @tparam Type Tuple type of any sizes.
  37. * @param value A tuple object of the given type.
  38. * @return The tuple itself if it contains more than one element, the first
  39. * element otherwise.
  40. */
  41. template<typename Type>
  42. constexpr decltype(auto) unwrap_tuple(Type &&value) noexcept {
  43. if constexpr(std::tuple_size_v<std::remove_reference_t<Type>> == 1u) {
  44. return std::get<0>(std::forward<Type>(value));
  45. } else {
  46. return std::forward<Type>(value);
  47. }
  48. }
  49. /**
  50. * @brief Utility class to forward-and-apply tuple objects.
  51. * @tparam Func Type of underlying invocable object.
  52. */
  53. template<typename Func>
  54. struct forward_apply: private Func {
  55. /**
  56. * @brief Constructs a forward-and-apply object.
  57. * @tparam Args Types of arguments to use to construct the new instance.
  58. * @param args Parameters to use to construct the instance.
  59. */
  60. template<typename... Args>
  61. constexpr forward_apply(Args &&...args) noexcept(std::is_nothrow_constructible_v<Func, Args...>)
  62. : Func{std::forward<Args>(args)...} {}
  63. /**
  64. * @brief Forwards and applies the arguments with the underlying function.
  65. * @tparam Type Tuple-like type to forward to the underlying function.
  66. * @param args Parameters to forward to the underlying function.
  67. * @return Return value of the underlying function, if any.
  68. */
  69. template<typename Type>
  70. constexpr decltype(auto) operator()(Type &&args) noexcept(noexcept(std::apply(std::declval<Func &>(), args))) {
  71. return std::apply(static_cast<Func &>(*this), std::forward<Type>(args));
  72. }
  73. /*! @copydoc operator()() */
  74. template<typename Type>
  75. constexpr decltype(auto) operator()(Type &&args) const noexcept(noexcept(std::apply(std::declval<const Func &>(), args))) {
  76. return std::apply(static_cast<const Func &>(*this), std::forward<Type>(args));
  77. }
  78. };
  79. /**
  80. * @brief Deduction guide.
  81. * @tparam Func Type of underlying invocable object.
  82. */
  83. template<typename Func>
  84. forward_apply(Func) -> forward_apply<std::remove_reference_t<std::remove_cv_t<Func>>>;
  85. } // namespace entt
  86. #endif