/* * Legyen benne zipwith * * Itt az a trukk, hogy az iterator az impl**-ot tarol, igy a zipwith * kiertekeles utan atirja az adatszerkezetet, tehat ketszer nem szamolja ki * ugyanazt az erteket. * * Legnagyobb fajdalmamra nem sikerult osszeraknom ilyesmit: * for(int i=0; i<10; ++i) * s=i< #include #include #include #if __GNUC__ > 4 || \ (__GNUC__ == 4 && (__GNUC_MINOR__ >= 7)) #define HAVE_LITERALS #endif template struct storage_type { typedef typename std::conditional< std::is_lvalue_reference::type>::value, typename std::remove_const::type, typename std::remove_reference::type>::type >::type type; }; template struct stream { protected: struct impl; public: typedef T value_type; stream(const stream &o) : impl_(o.impl_->clone()) { } stream(stream &&o) : impl_(0) { std::swap(impl_, o.impl_); } stream & operator = (stream &&o) { if(this != &o) { std::swap(impl_, o.impl_); return *this; } } ~stream() { delete impl_; } struct iterator { iterator& operator ++() { (*impl_)->next(*this); return *this; } const T& operator *() const { return (*impl_)->get(*this); } friend class stream; protected: iterator(impl ** impl) :impl_(impl) { } impl **impl_; }; iterator begin() const { return iterator(&impl_); } protected: struct impl { virtual ~impl() {} virtual const T &get(const iterator &) = 0; virtual void next(iterator &) = 0; virtual impl* clone() = 0; }; mutable impl * impl_; stream(impl *i) :impl_(i) { } template struct addimpl: public impl { addimpl(const T &a, ST &&s) : a_(a), s_(std::forward(s)) { } const T &get(const iterator &) { return a_; } void next(iterator &it) { it.impl_ = const_cast(&s_.impl_); } impl *clone() { return new addimpl(a_, std::forward(s_)); } private: const T a_; typename storage_type::type s_; }; template struct mapimpl2: public impl { mapimpl2(Op op, ST &&s) :s_(std::forward(s)), it1(s_.begin()), op_(op) { } const T &get(const iterator &it) { *(it.impl_)=new addimpl&&>(op_(*it1), stream(this)); ++it1; return *it; } void next(iterator &it) { *(it.impl_)=new addimpl&&>(op_(*it1), stream(this)); ++it1; ++it; } impl *clone() { return new mapimpl2(op_, std::forward(s_)); } private: typename storage_type::type s_; iterator it1; Op op_; }; template struct mapimpl: public impl { mapimpl(Op op, ST &&s) : s_(std::forward(s)), op_(op) { } const T &get(const iterator &it) { impl *x = new mapimpl2(op_, std::forward(s_)); *(it.impl_) = x; delete this; return *it; } void next(iterator &it) { impl *x = new mapimpl2(op_, std::forward(s_)); *(it.impl_) = x; delete this; ++it; } impl *clone() { return new mapimpl(op_, std::forward(s_)); } private: typename storage_type::type s_; Op op_; }; template struct zipimpl: public impl { zipimpl(Op op, ST1 &&s1, ST2 &&s2) :s1_(std::forward(s1)), s2_(std::forward(s2)), op_(op) { } const T &get(const iterator &it) { impl *x = new zipimpl2(op_, std::forward(s1_), std::forward(s2_)); *(it.impl_) = x; delete this; return *it; } void next(iterator &it) { impl *x = new zipimpl2(op_, std::forward(s1_), std::forward(s2_)); *(it.impl_) = x; delete this; ++it; } impl *clone() { return new zipimpl(op_, std::forward(s1_), std::forward(s2_)); } private: typename storage_type::type s1_; typename storage_type::type s2_; Op op_; }; template struct zipimpl2: public impl { zipimpl2(Op op, ST1 &&s1, ST2 &&s2) :s1_(std::forward(s1)),s2_(std::forward(s2)), it1(s1_.begin()), it2(s2_.begin()), op_(op) { } const T &get(const iterator &it) { *(it.impl_)=new addimpl&&>(op_(*it1, *it2), stream(this)); ++it1; ++it2; return *it; } void next(iterator &it) { *(it.impl_)=new addimpl&&>(op_(*it1, *it2), stream(this)); ++it1; ++it2; ++it; } impl *clone() { return new zipimpl2(op_, std::forward(s1_), std::forward(s2_)); } private: typename storage_type::type s1_; typename storage_type::type s2_; iterator it1, it2; Op op_; }; public: template friend stream operator <<= (const U& a, S && s); template static stream zipwith(Op op, ST1 &&s1, ST2 &&s2) { return stream(new zipimpl(op, std::forward(s1), std::forward(s2))); } template static stream map(Op op, ST1 &&s1) { return stream(new mapimpl(op, std::forward(s1))); } static stream pure(const T& v) { stream s = v<<=s; return s; } }; template struct stream_value_type { typedef typename std::remove_reference::type::value_type type; }; template ::type> stream operator <<= (const U& a, S && s) { return stream(new typename stream::template addimpl(a, std::forward(s))); } template::type> stream operator +(ST1 &&s1, ST2 &&s2) { return stream::zipwith(std::plus(), std::forward(s1), std::forward(s2)); } template::type> stream operator -(ST1 &&s1, ST2 &&s2) { return stream::zipwith(std::minus(), std::forward(s1), std::forward(s2)); } template::type> stream operator *(ST1 &&s1, ST2 &&s2) { return stream::zipwith(std::multiplies(), std::forward(s1), std::forward(s2)); } template::type> stream operator /(ST1 &&s1, ST2 &&s2) { return stream::zipwith(std::divides(), std::forward(s1), std::forward(s2)); } template::type> stream operator %(ST1 &&s1, ST2 &&s2) { return stream::zipwith(std::modulus(), std::forward(s1), std::forward(s2)); } template::type> stream operator -(ST &&s) { return stream::map(std::negate(), std::forward(s)); } #ifdef HAVE_LITERALS struct stream_proxy { stream_proxy(unsigned long long i): x(i) {} template operator stream () { stream a = static_cast(x)<<=a; return a; } unsigned long long x; }; stream_proxy operator "" _s (unsigned long long i) { return stream_proxy(i); } #endif//HAVE_LITERALS #endif//__stream_h__