mirror of
https://github.com/Naios/continuable.git
synced 2025-12-06 16:56:44 +08:00
Add cti::populate and make use of it in tests
This commit is contained in:
parent
86c3815ae0
commit
de40af0927
@ -31,7 +31,10 @@
|
||||
#ifndef CONTINUABLE_COMPOSITIONS_HPP_INCLUDED
|
||||
#define CONTINUABLE_COMPOSITIONS_HPP_INCLUDED
|
||||
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <continuable/detail/composition-all.hpp>
|
||||
#include <continuable/detail/composition-any.hpp>
|
||||
@ -242,6 +245,49 @@ template <
|
||||
auto when_any(Iterator begin, Iterator end) {
|
||||
return when_any(detail::range::persist_range(begin, end));
|
||||
}
|
||||
|
||||
/// Populates a homogeneous container from the given arguments.
|
||||
/// All arguments need to be convertible to the first one,
|
||||
/// by default std::vector is used as container type.
|
||||
///
|
||||
/// This method mainly helps to create a homogeneous container from
|
||||
/// a runtime known count of continuables which type isn't exactly known.
|
||||
/// All continuables which are passed to this function should be originating
|
||||
/// from the same source or a method called with the same types of arguments:
|
||||
/// ```cpp
|
||||
/// auto container = cti::populate(cti::make_ready_continuable(0),
|
||||
/// cti::make_ready_continuable(1)),
|
||||
///
|
||||
/// for (int i = 2; i < 5; ++i) {
|
||||
/// // You may add more continuables to the container afterwards
|
||||
/// container.emplace_back(cti::make_ready_continuable(i));
|
||||
/// }
|
||||
///
|
||||
/// cti::when_any(std::move(container))
|
||||
/// .then([](int) {
|
||||
/// // ...
|
||||
/// });
|
||||
/// ```
|
||||
/// Additionally it is possible to change the targeted container as below:
|
||||
/// ```cpp
|
||||
/// auto container = cti::populate<std::list>(cti::make_ready_continuable(0),
|
||||
/// cti::make_ready_continuable(1)),
|
||||
/// ```
|
||||
///
|
||||
/// \tparam C The container type which is used to store the arguments into.
|
||||
///
|
||||
/// \since 3.0.0
|
||||
template <template <typename, typename> class C = std::vector, typename First,
|
||||
typename... Args>
|
||||
C<std::decay_t<First>, std::allocator<std::decay_t<First>>>
|
||||
populate(First&& first, Args&&... args) {
|
||||
C<std::decay_t<First>, std::allocator<std::decay_t<First>>> container;
|
||||
container.reserve(1 + sizeof...(Args));
|
||||
container.emplace_back(std::forward<First>(first));
|
||||
(void)std::initializer_list<int>{
|
||||
0, ((void)container.emplace_back(std::forward<Args>(args)), 0)...};
|
||||
return container; // RVO
|
||||
}
|
||||
} // namespace cti
|
||||
|
||||
#endif // CONTINUABLE_COMPOSITIONS_HPP_INCLUDED
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
|
||||
#include <iterator>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <continuable/detail/traits.hpp>
|
||||
@ -52,11 +53,11 @@ struct is_iterator<T,
|
||||
template <typename Iterator>
|
||||
auto persist_range(Iterator begin, Iterator end) {
|
||||
std::vector<typename std::iterator_traits<Iterator>::value_type> storage;
|
||||
|
||||
storage.insert(storage.end(), std::make_move_iterator(begin),
|
||||
std::make_move_iterator(end));
|
||||
|
||||
return storage; // RVO
|
||||
// TODO Find out why the superior idiom below has issues with move only types:
|
||||
// storage.insert(storage.end(), std::make_move_iterator(begin),
|
||||
// std::make_move_iterator(end));
|
||||
std::move(begin, end, std::back_inserter(storage));
|
||||
return storage;
|
||||
}
|
||||
} // namespace range
|
||||
} // namespace detail
|
||||
|
||||
@ -126,19 +126,21 @@ void old() {
|
||||
int main(int, char**) {
|
||||
using namespace cti::detail;
|
||||
|
||||
{
|
||||
cti::when_seq(
|
||||
cti::make_ready_continuable(0, 1), 2, //< See this plain value
|
||||
std::vector<cti::continuable<int>>{cti::make_ready_continuable(3),
|
||||
cti::make_ready_continuable(4)},
|
||||
cti::populate(cti::make_ready_continuable(3),
|
||||
cti::make_ready_continuable(4)),
|
||||
std::make_tuple(std::make_tuple(cti::make_ready_continuable(5))))
|
||||
.then([](int r0, int r1, int r2, std::vector<int> r34,
|
||||
std::tuple<std::tuple<int>> r5) {
|
||||
// ...
|
||||
util::unused(r0, r1, r2, r34, r5);
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<cti::continuable<int>> v{cti::make_ready_continuable(8),
|
||||
cti::make_ready_continuable(9)};
|
||||
auto v = cti::populate(cti::make_ready_continuable(8),
|
||||
cti::make_ready_continuable(9));
|
||||
|
||||
cti::when_seq(v.begin(), v.end()).then([](auto o2) {
|
||||
// ...
|
||||
@ -162,8 +164,8 @@ int main(int, char**) {
|
||||
|
||||
cti::when_all(
|
||||
cti::make_ready_continuable(0, 1), 2, //< See this plain value
|
||||
std::vector<cti::continuable<int>>{cti::make_ready_continuable(3),
|
||||
cti::make_ready_continuable(4)},
|
||||
cti::populate(cti::make_ready_continuable(3),
|
||||
cti::make_ready_continuable(4)),
|
||||
std::make_tuple(std::make_tuple(cti::make_ready_continuable(5))))
|
||||
.then([](int r0, int r1, int r2, std::vector<int> r34,
|
||||
std::tuple<std::tuple<int>> r5) {
|
||||
|
||||
@ -75,15 +75,8 @@ void test_all_seq_aggregate(Supplier&& supply, AggregateConnector&& ag) {
|
||||
}
|
||||
|
||||
{
|
||||
using type_t = std::decay_t<decltype(
|
||||
std::declval<Supplier>()(std::declval<int>(), std::declval<int>()))>;
|
||||
|
||||
std::vector<type_t> v;
|
||||
v.push_back(supply(1, 2));
|
||||
v.push_back(supply(3, 4));
|
||||
v.push_back(supply(5, 6));
|
||||
|
||||
auto chain = ag(std::make_tuple(std::move(v)));
|
||||
auto chain = ag(std::make_tuple(
|
||||
cti::populate(supply(1, 2), supply(3, 4), supply(5, 6))));
|
||||
EXPECT_ASYNC_RESULT(std::move(chain),
|
||||
std::make_tuple(std::vector<std::tuple<int, int>>{
|
||||
{1, 2}, {3, 4}, {5, 6}}));
|
||||
|
||||
@ -68,15 +68,8 @@ TYPED_TEST(single_dimension_tests, is_logical_any_connectable) {
|
||||
}
|
||||
|
||||
{
|
||||
using type_t = std::decay_t<decltype(std::declval<TestFixture>().supply(
|
||||
std::declval<int>(), std::declval<int>()))>;
|
||||
|
||||
std::vector<type_t> v;
|
||||
v.push_back(this->supply(1, 2));
|
||||
v.push_back(this->supply(3, 4));
|
||||
v.push_back(this->supply(5, 6));
|
||||
|
||||
auto chain = cti::when_any(std::make_tuple(std::move(v)));
|
||||
auto chain = cti::when_any(std::make_tuple(std::move(cti::populate(
|
||||
this->supply(1, 2), this->supply(3, 4), this->supply(5, 6)))));
|
||||
EXPECT_ASYNC_RESULT(std::move(chain), 1, 2);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user