tuple: forward_apply functional type (#876)

This commit is contained in:
Dominic Koepke
2022-04-28 15:54:02 +02:00
committed by Michele Caini
parent 1330cb9126
commit ef6e47f625
2 changed files with 46 additions and 0 deletions

View File

@@ -24,6 +24,46 @@ constexpr decltype(auto) unwrap_tuple(Type &&value) ENTT_NOEXCEPT {
}
}
/**
* @brief Utility class to forward-and-apply tuple objects.
* @tparam Func Type of underlying invocable object.
*/
template<typename Func>
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<class... Args>
constexpr forward_apply(Args &&...args) ENTT_NOEXCEPT_IF((std::is_nothrow_constructible_v<Func, Args...>))
: Func{std::forward<Args>(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<class Type>
constexpr decltype(auto) operator()(Type &&args) ENTT_NOEXCEPT_IF(noexcept(std::apply(std::declval<Func &>(), args))) {
return std::apply(static_cast<Func &>(*this), std::forward<Type>(args));
}
/*! @copydoc operator()() */
template<class Type>
constexpr decltype(auto) operator()(Type &&args) const ENTT_NOEXCEPT_IF(noexcept(std::apply(std::declval<const Func &>(), args))) {
return std::apply(static_cast<const Func &>(*this), std::forward<Type>(args));
}
};
/**
* @brief Deduction guide.
* @tparam Func Type of underlying invocable object.
*/
template<typename Func>
forward_apply(Func) -> forward_apply<std::remove_reference_t<std::remove_cv_t<Func>>>;
} // namespace entt
#endif

View File

@@ -23,3 +23,9 @@ TEST(Tuple, UnwrapTuple) {
ASSERT_EQ(entt::unwrap_tuple(multi), multi);
ASSERT_EQ(entt::unwrap_tuple(std::move(ref)), 42);
}
TEST(Tuple, ForwardApply) {
ASSERT_EQ(entt::forward_apply{[](auto &&...args) { return sizeof...(args); }}(std::make_tuple()), 0u);
ASSERT_EQ(entt::forward_apply{[](int i) { return i; }}(std::make_tuple(42)), 42);
ASSERT_EQ(entt::forward_apply{[](auto... args) { return (args + ...); }}(std::make_tuple('a', 1u)), 'b');
}