typedef typename std::decay<Value>::type StorageType;
/**
- * apply() - Send all values produced by this generator to given
- * handler until the handler returns false. Returns false if and only if the
- * handler returns false. Note: It should return true even if it completes
- * (without the handler returning false), as 'Chain' uses the return value of
- * apply to determine if it should process the second object in its chain.
+ * apply() - Send all values produced by this generator to given handler until
+ * the handler returns false. Returns false if and only if the handler passed
+ * in returns false. Note: It should return true even if it completes (without
+ * the handler returning false), as 'Chain' uses the return value of apply to
+ * determine if it should process the second object in its chain.
*/
template<class Handler>
bool apply(Handler&& handler) const;
{}
template<class Value,
- class Source,
- class Result = typename std::result_of<Predicate(Value)>::type>
- class Generator :
- public GenImpl<Result, Generator<Value, Source, Result>> {
+ class Source>
+ class Generator : public GenImpl<Value, Generator<Value, Source>> {
Source source_;
Predicate pred_;
public:
template<class Handler>
bool apply(Handler&& handler) const {
- return source_.apply([&](Value value) -> bool {
- return !pred_(std::forward<Value>(value))
- && handler(std::forward<Value>(value));
+ bool cancelled = false;
+ source_.apply([&](Value value) -> bool {
+ if (pred_(value)) { // un-forwarded to disable move
+ return false;
+ }
+ if (!handler(std::forward<Value>(value))) {
+ cancelled = true;
+ return false;
+ }
+ return true;
});
+ return !cancelled;
}
};
bool apply(Handler&& handler) const {
if (count_ == 0) { return false; }
size_t n = count_;
- return source_.apply([&](Value value) -> bool {
- if (!handler(std::forward<Value>(value))) {
- return false;
- }
- return --n;
- });
+ bool cancelled = false;
+ source_.apply([&](Value value) -> bool {
+ if (!handler(std::forward<Value>(value))) {
+ cancelled = true;
+ return false;
+ }
+ return --n;
+ });
+ return !cancelled;
}
};
template<class Handler>
bool apply(Handler&& handler) const {
if (count_ == 0) {
- return source_.apply(handler);
+ return source_.apply(std::forward<Handler>(handler));
}
size_t n = 0;
return source_.apply([&](Value value) -> bool {
}
TEST(Gen, Take) {
- auto expected = vector<int>{1, 4, 9, 16};
- auto actual =
+ {
+ auto expected = vector<int>{1, 4, 9, 16};
+ auto actual =
seq(1, 1000)
- | mapped([](int x) { return x * x; })
- | take(4)
- | as<vector<int>>();
- EXPECT_EQ(expected, actual);
+ | mapped([](int x) { return x * x; })
+ | take(4)
+ | as<vector<int>>();
+ EXPECT_EQ(expected, actual);
+ }
+ {
+ auto expected = vector<int>{ 0, 1, 4, 5, 8 };
+ auto actual
+ = ((seq(0) | take(2)) +
+ (seq(4) | take(2)) +
+ (seq(8) | take(2)))
+ | take(5)
+ | as<vector>();
+ EXPECT_EQ(expected, actual);
+ }
+ {
+ auto expected = vector<int>{ 0, 1, 4, 5, 8 };
+ auto actual
+ = seq(0)
+ | mapped([](int i) {
+ return seq(i * 4) | take(2);
+ })
+ | concat
+ | take(5)
+ | as<vector>();
+ EXPECT_EQ(expected, actual);
+ }
}
TEST(Gen, Sample) {
}
TEST(Gen, Until) {
- auto gen =
- seq(1) //infinite
- | mapped([](int x) { return x * x; })
- | until([](int x) { return x >= 1000; });
- EXPECT_EQ(31, gen | count);
+ {
+ auto expected = vector<int>{1, 4, 9, 16};
+ auto actual
+ = seq(1, 1000)
+ | mapped([](int x) { return x * x; })
+ | until([](int x) { return x > 20; })
+ | as<vector<int>>();
+ EXPECT_EQ(expected, actual);
+ }
+ {
+ auto expected = vector<int>{ 0, 1, 4, 5, 8 };
+ auto actual
+ = ((seq(0) | until([](int i) { return i > 1; })) +
+ (seq(4) | until([](int i) { return i > 5; })) +
+ (seq(8) | until([](int i) { return i > 9; })))
+ | until([](int i) { return i > 8; })
+ | as<vector<int>>();
+ EXPECT_EQ(expected, actual);
+ }
+ /*
+ {
+ auto expected = vector<int>{ 0, 1, 5, 6, 10 };
+ auto actual
+ = seq(0)
+ | mapped([](int i) {
+ return seq(i * 5) | until([=](int j) { return j > i * 5 + 1; });
+ })
+ | concat
+ | until([](int i) { return i > 10; })
+ | as<vector<int>>();
+ EXPECT_EQ(expected, actual);
+ }
+ */
}
auto even = [](int i) -> bool { return i % 2 == 0; };