#include <iostream>
#include <vector>
#include <list>
#include <cstring>
#include <set>
#include <boost/iterator/filter_iterator.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/zip_iterator.hpp>
#include <boost/tuple/tuple.hpp>
#include <algorithm>
#include <memory>
template<typename IterT>
class iterator_stream {
private:
IterT begin_, end_;
public:
iterator_stream(IterT begin, IterT end) : begin_(std::move(begin)), end_(std::move(end)) { }
IterT begin() const {
return begin_;
}
IterT end() const {
return end_;
}
template<typename CallbackT> void
for_each(CallbackT cb) {
std::for_each(begin_, end_, cb);
}
template<typename PredicateT>
iterator_stream<boost::filter_iterator<PredicateT, IterT>> filter(PredicateT predicate) {
typedef boost::filter_iterator<PredicateT, IterT> FilterIterT;
return iterator_stream<FilterIterT>(FilterIterT(predicate, begin_, end_), FilterIterT(predicate, end_, end_));
}
template<typename MapperT>
iterator_stream<boost::transform_iterator<MapperT, IterT>> map(MapperT mapper) {
typedef boost::transform_iterator<MapperT, IterT> MapIterT;
return iterator_stream<MapIterT>(MapIterT(begin_, mapper), MapIterT(end_, mapper));
}
};
template<typename ContainerT>
auto stream(ContainerT& c) -> iterator_stream<typename ContainerT::iterator> {
return iterator_stream<typename ContainerT::iterator>(c.begin(), c.end());
}
template<typename T, std::size_t Size>
iterator_stream<T*> stream(T (&a)[Size]) {
return iterator_stream<T*>(a, a + Size);
}
template<typename Iter1T, typename Iter2T>
iterator_stream<boost::zip_iterator<boost::tuple<Iter1T, Iter2T>>> zip(iterator_stream<Iter1T> const& s1, iterator_stream<Iter2T> const& s2) {
typedef boost::zip_iterator<boost::tuple<Iter1T, Iter2T>> ZipIterT;
return iterator_stream<ZipIterT>(
ZipIterT(boost::make_tuple(s1.begin(), s2.begin())),
ZipIterT(boost::make_tuple(s1.end(), s2.end())));
}
int main() {
std::vector<char const*> vec = { "Hello", "World", "!"};
stream(vec)
.filter([](auto& str) { return std::strlen(str) > 1; })
.map([](auto& str) { return std::strlen(str); })
.for_each([](auto len) { std::cout << len << std::endl; });
std::list<std::string> en = { "Hello", "World", "Asshole" };
char const* de[] = { "Hallo", "Welt", "Arschloch" };
std::set<std::string> insults = { "Asshole" };
zip(stream(en), stream(de))
.filter([&] (auto const& t) { return insults.find(boost::get<0>(t)) == insults.end(); })
.map([](auto const& t) { return boost::get<0>(t) + " - " + boost::get<1>(t); })
.for_each([] (auto const& str) { std::cout << str << std::endl; });
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8bGlzdD4KI2luY2x1ZGUgPGNzdHJpbmc+CiNpbmNsdWRlIDxzZXQ+CgojaW5jbHVkZSA8Ym9vc3QvaXRlcmF0b3IvZmlsdGVyX2l0ZXJhdG9yLmhwcD4KI2luY2x1ZGUgPGJvb3N0L2l0ZXJhdG9yL3RyYW5zZm9ybV9pdGVyYXRvci5ocHA+CiNpbmNsdWRlIDxib29zdC9pdGVyYXRvci96aXBfaXRlcmF0b3IuaHBwPgojaW5jbHVkZSA8Ym9vc3QvdHVwbGUvdHVwbGUuaHBwPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8bWVtb3J5PgoKdGVtcGxhdGU8dHlwZW5hbWUgSXRlclQ+CmNsYXNzIGl0ZXJhdG9yX3N0cmVhbSB7CnByaXZhdGU6CglJdGVyVCBiZWdpbl8sIGVuZF87CgkKcHVibGljOgoJaXRlcmF0b3Jfc3RyZWFtKEl0ZXJUIGJlZ2luLCBJdGVyVCBlbmQpIDogYmVnaW5fKHN0ZDo6bW92ZShiZWdpbikpLCBlbmRfKHN0ZDo6bW92ZShlbmQpKSB7IH0KCQoJSXRlclQgYmVnaW4oKSBjb25zdCB7CgkJcmV0dXJuIGJlZ2luXzsKCX0KCQoJSXRlclQgZW5kKCkgY29uc3QgewoJCXJldHVybiBlbmRfOwoJfQoJCgl0ZW1wbGF0ZTx0eXBlbmFtZSBDYWxsYmFja1Q+IHZvaWQKCWZvcl9lYWNoKENhbGxiYWNrVCBjYikgewoJCXN0ZDo6Zm9yX2VhY2goYmVnaW5fLCBlbmRfLCBjYik7Cgl9CgkKCXRlbXBsYXRlPHR5cGVuYW1lIFByZWRpY2F0ZVQ+CglpdGVyYXRvcl9zdHJlYW08Ym9vc3Q6OmZpbHRlcl9pdGVyYXRvcjxQcmVkaWNhdGVULCBJdGVyVD4+IGZpbHRlcihQcmVkaWNhdGVUIHByZWRpY2F0ZSkgewoJCXR5cGVkZWYgYm9vc3Q6OmZpbHRlcl9pdGVyYXRvcjxQcmVkaWNhdGVULCBJdGVyVD4gRmlsdGVySXRlclQ7CgkJcmV0dXJuIGl0ZXJhdG9yX3N0cmVhbTxGaWx0ZXJJdGVyVD4oRmlsdGVySXRlclQocHJlZGljYXRlLCBiZWdpbl8sIGVuZF8pLCBGaWx0ZXJJdGVyVChwcmVkaWNhdGUsIGVuZF8sIGVuZF8pKTsKCX0KCQoJdGVtcGxhdGU8dHlwZW5hbWUgTWFwcGVyVD4KCWl0ZXJhdG9yX3N0cmVhbTxib29zdDo6dHJhbnNmb3JtX2l0ZXJhdG9yPE1hcHBlclQsIEl0ZXJUPj4gbWFwKE1hcHBlclQgbWFwcGVyKSB7CgkJdHlwZWRlZiBib29zdDo6dHJhbnNmb3JtX2l0ZXJhdG9yPE1hcHBlclQsIEl0ZXJUPiBNYXBJdGVyVDsKCQlyZXR1cm4gaXRlcmF0b3Jfc3RyZWFtPE1hcEl0ZXJUPihNYXBJdGVyVChiZWdpbl8sIG1hcHBlciksIE1hcEl0ZXJUKGVuZF8sIG1hcHBlcikpOwoJfQoJCn07Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBDb250YWluZXJUPgphdXRvIHN0cmVhbShDb250YWluZXJUJiBjKSAtPiBpdGVyYXRvcl9zdHJlYW08dHlwZW5hbWUgQ29udGFpbmVyVDo6aXRlcmF0b3I+IHsKCXJldHVybiBpdGVyYXRvcl9zdHJlYW08dHlwZW5hbWUgQ29udGFpbmVyVDo6aXRlcmF0b3I+KGMuYmVnaW4oKSwgYy5lbmQoKSk7Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFQsIHN0ZDo6c2l6ZV90IFNpemU+Cml0ZXJhdG9yX3N0cmVhbTxUKj4gc3RyZWFtKFQgKCZhKVtTaXplXSkgewoJcmV0dXJuIGl0ZXJhdG9yX3N0cmVhbTxUKj4oYSwgYSArIFNpemUpOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBJdGVyMVQsIHR5cGVuYW1lIEl0ZXIyVD4KaXRlcmF0b3Jfc3RyZWFtPGJvb3N0Ojp6aXBfaXRlcmF0b3I8Ym9vc3Q6OnR1cGxlPEl0ZXIxVCwgSXRlcjJUPj4+IHppcChpdGVyYXRvcl9zdHJlYW08SXRlcjFUPiBjb25zdCYgczEsIGl0ZXJhdG9yX3N0cmVhbTxJdGVyMlQ+IGNvbnN0JiBzMikgewoJdHlwZWRlZiBib29zdDo6emlwX2l0ZXJhdG9yPGJvb3N0Ojp0dXBsZTxJdGVyMVQsIEl0ZXIyVD4+IFppcEl0ZXJUOwoJcmV0dXJuIGl0ZXJhdG9yX3N0cmVhbTxaaXBJdGVyVD4oCgkJWmlwSXRlclQoYm9vc3Q6Om1ha2VfdHVwbGUoczEuYmVnaW4oKSwgczIuYmVnaW4oKSkpLAoJCVppcEl0ZXJUKGJvb3N0OjptYWtlX3R1cGxlKHMxLmVuZCgpLCBzMi5lbmQoKSkpKTsKfQoKaW50IG1haW4oKSB7CglzdGQ6OnZlY3RvcjxjaGFyIGNvbnN0Kj4gdmVjID0geyAiSGVsbG8iLCAiV29ybGQiLCAiISJ9OwoJc3RyZWFtKHZlYykKCQkuZmlsdGVyKFtdKGF1dG8mIHN0cikgeyByZXR1cm4gc3RkOjpzdHJsZW4oc3RyKSA+IDE7IH0pCgkJLm1hcChbXShhdXRvJiBzdHIpIHsgcmV0dXJuIHN0ZDo6c3RybGVuKHN0cik7IH0pCgkJLmZvcl9lYWNoKFtdKGF1dG8gbGVuKSB7IHN0ZDo6Y291dCA8PCBsZW4gPDwgc3RkOjplbmRsOyB9KTsKCQkKCXN0ZDo6bGlzdDxzdGQ6OnN0cmluZz4gZW4gPSB7ICJIZWxsbyIsICJXb3JsZCIsICJBc3Nob2xlIiB9OwoJY2hhciBjb25zdCogZGVbXSA9IHsgIkhhbGxvIiwgIldlbHQiLCAiQXJzY2hsb2NoIiB9OwoJc3RkOjpzZXQ8c3RkOjpzdHJpbmc+IGluc3VsdHMgPSB7ICJBc3Nob2xlIiB9OwoJemlwKHN0cmVhbShlbiksIHN0cmVhbShkZSkpCgkJLmZpbHRlcihbJl0gKGF1dG8gY29uc3QmIHQpIHsgcmV0dXJuIGluc3VsdHMuZmluZChib29zdDo6Z2V0PDA+KHQpKSA9PSBpbnN1bHRzLmVuZCgpOyB9KQoJCS5tYXAoW10oYXV0byBjb25zdCYgdCkgeyByZXR1cm4gYm9vc3Q6OmdldDwwPih0KSArICIgLSAiICsgYm9vc3Q6OmdldDwxPih0KTsgfSkKCQkuZm9yX2VhY2goW10gKGF1dG8gY29uc3QmIHN0cikgeyBzdGQ6OmNvdXQgPDwgc3RyIDw8IHN0ZDo6ZW5kbDsgfSk7Cn0=