diff --git a/libvmake/examples/input.cpp b/libvmake/examples/input.cpp new file mode 100644 index 0000000..402c0c6 --- /dev/null +++ b/libvmake/examples/input.cpp @@ -0,0 +1,11 @@ +#include "../vmake.hpp" +using namespace std; + +int main() { + int n; + cin >> n; + vmake::output_n(cout, n, " ", vmake::transform(vmake::extract(istream_iterator(cin)), [](int x) { + return x * x; + })); + return 0; +} diff --git a/libvmake/vmake.hpp b/libvmake/vmake.hpp index dbb2734..f7559ec 100644 --- a/libvmake/vmake.hpp +++ b/libvmake/vmake.hpp @@ -99,12 +99,12 @@ struct empty_sequence { }; template -struct extractor { +struct ranged_iterator_extractor { using result = typename std::remove_reference())>::type; ContIt cur, end; - extractor(const ContIt &begin, const ContIt &end) : cur(begin), end(end) {} + ranged_iterator_extractor(const ContIt &begin, const ContIt &end) : cur(begin), end(end) {} bool is_terminated() const noexcept { return cur == end; @@ -116,6 +116,47 @@ struct extractor { } }; +template +struct iterator_extractor { + using result = typename std::remove_reference())>::type; + + ContIt it; + bool added; + + iterator_extractor(const ContIt &begin) : it(begin), added(false) {}; + + constexpr bool is_terminated() const noexcept { + return false; + } + + auto operator()() { + // WARN: use for strange iterators such as std::istream_iterator + // do NOT try to optimize this into *it++ + if (added) return *++it; + added = true; + return *it; + } +}; + +} // namespace details + +template +inline auto extract(const ContIt &begin, const ContIt &end) { + return details::ranged_iterator_extractor(begin, end); +} + +template +inline auto extract(const ContIt &begin) { + return details::iterator_extractor(begin); +} + +template +inline auto extract_n(const ContIt &begin, size_t n) { + return take(details::iterator_extractor(begin), n); +} + +namespace details { + template struct generator { using result = typename std::result_of::type; @@ -236,11 +277,6 @@ inline OutputIt copy_n(OutputIt it, size_t n, Gen&& g) { return it; } -template -inline auto extract(const ContIt &begin, const ContIt &end) { - return details::extractor(begin, end); -} - template struct concator { using result = typename Gen1::result; @@ -308,7 +344,7 @@ inline auto output(OutputStream& out, Gen &&g) { } template -inline auto output_n(OutputStream& out, const char *delim, size_t n, Gen &&g) { +inline auto output_n(OutputStream& out, size_t n, const char *delim, Gen &&g) { return copy_n(std::ostream_iterator::type::result>(out, delim), n, std::move(g)); }