#ifndef ENTT_CORE_TUPLE_HPP #define ENTT_CORE_TUPLE_HPP #include #include #include namespace entt { /** * @cond TURN_OFF_DOXYGEN * Internal details not to be documented. */ namespace internal { template struct is_tuple_impl: std::false_type {}; template struct is_tuple_impl>: std::true_type {}; } // namespace internal /** * Internal details not to be documented. * @endcond */ /** * @brief Provides the member constant `value` to true if a given type is a * tuple, false otherwise. * @tparam Type The type to test. */ template struct is_tuple: internal::is_tuple_impl> {}; /** * @brief Helper variable template. * @tparam Type The type to test. */ template inline constexpr bool is_tuple_v = is_tuple::value; /** * @brief Utility function to unwrap tuples of a single element. * @tparam Type Tuple type of any sizes. * @param value A tuple object of the given type. * @return The tuple itself if it contains more than one element, the first * element otherwise. */ template constexpr decltype(auto) unwrap_tuple(Type &&value) noexcept { if constexpr(std::tuple_size_v> == 1u) { return std::get<0>(std::forward(value)); } else { return std::forward(value); } } /** * @brief Utility class to forward-and-apply tuple objects. * @tparam Func Type of underlying invocable object. */ template struct forward_apply: private Func { /** * @brief Constructs a forward-and-apply object. * @tparam Args Types of arguments to use to construct the new instance. * @param args Parameters to use to construct the instance. */ template constexpr forward_apply(Args &&...args) noexcept(std::is_nothrow_constructible_v) : Func{std::forward(args)...} {} /** * @brief Forwards and applies the arguments with the underlying function. * @tparam Type Tuple-like type to forward to the underlying function. * @param args Parameters to forward to the underlying function. * @return Return value of the underlying function, if any. */ template constexpr decltype(auto) operator()(Type &&args) noexcept(noexcept(std::apply(std::declval(), args))) { return std::apply(static_cast(*this), std::forward(args)); } /*! @copydoc operator()() */ template constexpr decltype(auto) operator()(Type &&args) const noexcept(noexcept(std::apply(std::declval(), args))) { return std::apply(static_cast(*this), std::forward(args)); } }; /** * @brief Deduction guide. * @tparam Func Type of underlying invocable object. */ template forward_apply(Func) -> forward_apply>>; } // namespace entt #endif