public:
RangeConcat() { }
- template<class Range,
- class Source,
+ template<class Source,
+ class Range,
class InnerValue = typename ValueTypeOfRange<Range>::RefType>
class Generator
- : public GenImpl<InnerValue, Generator<Range, Source, InnerValue>> {
+ : public GenImpl<InnerValue, Generator<Source, Range, InnerValue>> {
Source source_;
public:
explicit Generator(Source source)
template<class Value,
class Source,
- class Gen = Generator<Value, Source>>
+ class Gen = Generator<Source, Value>>
Gen compose(GenImpl<Value, Source>&& source) const {
return Gen(std::move(source.self()));
}
template<class Value,
class Source,
- class Gen = Generator<Value, Source>>
+ class Gen = Generator<Source, Value>>
Gen compose(const GenImpl<Value, Source>& source) const {
return Gen(source.self());
}
};
-
-/**
- * Guard - For handling exceptions from downstream computation. Requires the
- * type of exception to catch, and handler function to invoke in the event of
- * the exception. Note that the handler may:
- * 1) return true to continue processing the sequence
- * 2) return false to end the sequence immediately
- * 3) throw, to pass the exception to the next catch
- * The handler must match the signature 'bool(Exception&, Value)'.
- *
- * This type is used through the `guard` helper, like so:
- *
- * auto indexes
- * = byLine(STDIN_FILENO)
- * | guard<std::runtime_error>([](std::runtime_error& e,
- * StringPiece sp) {
- * LOG(ERROR) << sp << ": " << e.str();
- * return true; // continue processing subsequent lines
- * })
- * | eachTo<int>()
- * | as<vector>();
- **/
-template<class Exception,
- class ErrorHandler>
-class Guard : public Operator<Guard<Exception, ErrorHandler>> {
- ErrorHandler handler_;
- public:
- Guard(ErrorHandler handler)
- : handler_(std::move(handler)) {}
-
- template<class Value,
- class Source>
- class Generator : public GenImpl<Value, Generator<Value, Source>> {
- Source source_;
- ErrorHandler handler_;
- public:
- explicit Generator(Source source,
- ErrorHandler handler)
- : source_(std::move(source)),
- handler_(std::move(handler)) {}
-
- template<class Handler>
- bool apply(Handler&& handler) const {
- return source_.apply([&](Value value) {
- try {
- handler(std::forward<Value>(value));
- return true;
- } catch (Exception& e) {
- return handler_(e, std::forward<Value>(value));
- }
- });
- }
-
- static constexpr bool infinite = Source::infinite;
- };
-
- template<class Value,
- class Source,
- class Gen = Generator<Value, Source>>
- Gen compose(GenImpl<Value, Source>&& source) const {
- return Gen(std::move(source.self()), handler_);
- }
-
- template<class Value,
- class Source,
- class Gen = Generator<Value, Source>>
- Gen compose(const GenImpl<Value, Source>& source) const {
- return Gen(source.self(), handler_);
- }
-};
} //::detail
/**
FileGenBufferedTest,
::testing::Values(0, 1, 2, 4, 8, 64, 4096));
-TEST(Gen, Guard) {
- using std::runtime_error;
- EXPECT_THROW(from({"1", "a", "3"})
- | eachTo<int>()
- | sum,
- runtime_error);
- EXPECT_EQ(4,
- from({"1", "a", "3"})
- | guard<runtime_error>([](runtime_error&, const char*) {
- return true; // continue
- })
- | eachTo<int>()
- | sum);
- EXPECT_EQ(1,
- from({"1", "a", "3"})
- | guard<runtime_error>([](runtime_error&, const char*) {
- return false; // break
- })
- | eachTo<int>()
- | sum);
- EXPECT_THROW(from({"1", "a", "3"})
- | guard<runtime_error>([](runtime_error&, const char* v) {
- if (v[0] == 'a') {
- throw;
- }
- return true;
- })
- | eachTo<int>()
- | sum,
- runtime_error);
-}
-
int main(int argc, char *argv[]) {
testing::InitGoogleTest(&argc, argv);
google::ParseCommandLineFlags(&argc, &argv, true);