Make it possible to apply transformations through pipes

This commit is contained in:
Denis Blank 2018-02-10 01:37:38 +01:00
parent e4ef3ccefb
commit 951155bc34
4 changed files with 51 additions and 10 deletions

View File

@ -392,6 +392,22 @@ public:
return std::move(*this).then(std::forward<T>(right));
}
/// The pipe operator | is an alias for the continuable::apply method.
///
/// \param transform The transformer which is applied.
///
/// \returns See the corresponding continuable_base::apply method for the
/// explanation of the return type.
///
/// \note You may create your own transformation through
/// calling make_transformation.
///
/// \since 3.0.0
template <typename T>
auto operator|(detail::types::transform<T> transform) && {
return std::move(*this).apply(std::move(transform));
}
/// Invokes both continuable_base objects parallel and calls the
/// callback with the result of both continuable_base objects.
///

View File

@ -32,8 +32,23 @@
#define CONTINUABLE_TRANSFORMS_HPP_INCLUDED
#include <continuable/detail/transforms.hpp>
#include <continuable/detail/types.hpp>
namespace cti {
/// A callable tag object which marks a wrapped callable object
/// as continuable transformation which enables some useful overloads.
///
/// \since 3.0.0
using detail::types::transform;
/// Wraps the given callable object into a transform class.
///
/// \since 3.0.0
template <typename T>
auto make_transform(T&& callable) {
return transform<std::decay_t<T>>(std::forward<T>(callable));
}
/// The namespace transforms declares callable objects that transform
/// any continuable_base to an object or to a continuable_base itself.
///
@ -61,10 +76,10 @@ namespace transforms {
///
/// \since 2.0.0
inline auto futurize() {
return [](auto&& continuable) {
return make_transform([](auto&& continuable) {
using detail::transforms::as_future;
return as_future(std::forward<decltype(continuable)>(continuable));
};
});
}
/// Returns a transform that if applied to a continuable, it will ignores all
@ -77,9 +92,9 @@ inline auto futurize() {
///
/// \since 2.0.0
inline auto flatten() {
return [](auto&& continuable) {
return make_transform([](auto&& continuable) {
return std::forward<decltype(continuable)>(continuable).fail([](auto&&) {});
};
});
}
} // namespace transforms
} // namespace cti

View File

@ -31,6 +31,8 @@
#ifndef CONTINUABLE_DETAIL_TYPES_HPP_INCLUDED
#define CONTINUABLE_DETAIL_TYPES_HPP_INCLUDED
#include <utility>
#include <continuable/detail/features.hpp>
#ifndef CONTINUABLE_WITH_CUSTOM_ERROR_TYPE
@ -65,6 +67,16 @@ struct this_thread_executor_tag {};
/// A tag which is used to continue with an error
struct dispatch_error_tag {};
/// Marks a given callable object as transformation
template <typename T>
class transform : T {
public:
explicit transform(T callable) : T(std::move(callable)) {
}
using T::operator();
};
} // namespace types
} // namespace detail
} // namespace cti

View File

@ -56,12 +56,10 @@ TYPED_TEST(single_dimension_tests, are_convertible_to_futures) {
{
auto canary = std::make_tuple(0xFD, 0xF5);
auto future = this->supply()
.then([&] {
// ...
return canary;
})
.apply(cti::transforms::futurize());
auto future = this->supply().then([&] {
// ...
return canary;
}) | cti::transforms::futurize();
ASSERT_TRUE(is_ready(future));
EXPECT_EQ(future.get(), canary);