#ifndef ENTT_CORE_TUPLE_HPP #define ENTT_CORE_TUPLE_HPP #include "../stl/tuple.hpp" #include "../stl/type_traits.hpp" #include "../stl/utility.hpp" namespace entt { /** * @brief Provides the member constant `value` equal to true if a given type is * a tuple, false otherwise. * @tparam Type The type to test. */ template struct is_tuple: stl::false_type {}; /** * @copybrief is_tuple * @tparam Args Tuple template arguments. */ template struct is_tuple>: stl::true_type {}; /** * @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(stl::tuple_size_v> == 1u) { return stl::get<0>(stl::forward(value)); } else { return stl::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(stl::is_nothrow_constructible_v) : Func{stl::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(stl::apply(stl::declval(), args))) { return stl::apply(static_cast(*this), stl::forward(args)); } /*! @copydoc operator()() */ template constexpr decltype(auto) operator()(Type &&args) const noexcept(noexcept(stl::apply(stl::declval(), args))) { return stl::apply(static_cast(*this), stl::forward(args)); } }; /** * @brief Deduction guide. * @tparam Func Type of underlying invocable object. */ template forward_apply(Func) -> forward_apply>; } // namespace entt #endif