#ifndef DISTINCT_H_ #define DISTINCT_H_ #include #include template class Distinct { private: typedef typename boost::decay< typename boost::result_of::type >::type KeyType; public: typedef typename Source::ElementType ElementType; typedef typename Source::MarkerType MarkerType; public: Distinct(Source source, KeyExtract keyExtract) : source(source), keyExtract(keyExtract), hasKey(false) {} bool step() { if(!this->source.step() ) return false; while(this->hasKey && this->key == this->keyExtract(*this->source.get() ) ) { if(!this->source.step() ) return false; } this->hasKey = true; this->key = this->keyExtract(*this->source.get() ); return true; } ElementType* get() { return this->source.get(); } MarkerType mark() const { return this->source.mark(); } void restore(MarkerType mark) { this->source.restore(mark); this->hasKey = true; this->key = this->keyExtract(*this->source.get() ); } private: Source source; KeyType key; KeyExtract keyExtract; bool hasKey; }; namespace db { template struct DistinctOp { KeyExtract keyExtract; template friend Distinct operator|(Source source, const DistinctOp& op) { return Distinct(source, op.keyExtract); } }; template inline DistinctOp distinctBy(KeyExtract keyExtract) { DistinctOp result = {keyExtract}; return result; } } #endif