Bene, oggi stavo anche cercando una facile implementazione della raccolta in C ++ 11. In realtà sono rimasto deluso, perché tutto ciò che ho trovato è troppo lontano da cose come i generatori Python, o l'operatore di rendimento C # ... o troppo complicato.
Lo scopo è quello di fare una raccolta che emetterà i suoi oggetti solo quando sarà richiesta.
Volevo che fosse così:
auto emitter = on_range<int>(a, b).yield(
[](int i) {
/* do something with i */
return i * 2;
});
Ho trovato questo post, la migliore risposta IMHO era su boost.coroutine2, di Yongwei Wu . Poiché è il più vicino a ciò che l'autore voleva.
Vale la pena imparare le Couroutines boost .. E forse lo farò nei fine settimana. Ma finora sto usando la mia implementazione molto piccola. Spero che aiuti qualcun altro.
Di seguito è riportato un esempio di utilizzo e quindi implementazione.
Example.cpp
#include <iostream>
#include "Generator.h"
int main() {
typedef std::pair<int, int> res_t;
auto emitter = Generator<res_t, int>::on_range(0, 3)
.yield([](int i) {
return std::make_pair(i, i * i);
});
for (auto kv : emitter) {
std::cout << kv.first << "^2 = " << kv.second << std::endl;
}
return 0;
}
Generator.h
template<typename ResTy, typename IndexTy>
struct yield_function{
typedef std::function<ResTy(IndexTy)> type;
};
template<typename ResTy, typename IndexTy>
class YieldConstIterator {
public:
typedef IndexTy index_t;
typedef ResTy res_t;
typedef typename yield_function<res_t, index_t>::type yield_function_t;
typedef YieldConstIterator<ResTy, IndexTy> mytype_t;
typedef ResTy value_type;
YieldConstIterator(index_t index, yield_function_t yieldFunction) :
mIndex(index),
mYieldFunction(yieldFunction) {}
mytype_t &operator++() {
++mIndex;
return *this;
}
const value_type operator*() const {
return mYieldFunction(mIndex);
}
bool operator!=(const mytype_t &r) const {
return mIndex != r.mIndex;
}
protected:
index_t mIndex;
yield_function_t mYieldFunction;
};
template<typename ResTy, typename IndexTy>
class YieldIterator : public YieldConstIterator<ResTy, IndexTy> {
public:
typedef YieldConstIterator<ResTy, IndexTy> parent_t;
typedef IndexTy index_t;
typedef ResTy res_t;
typedef typename yield_function<res_t, index_t>::type yield_function_t;
typedef ResTy value_type;
YieldIterator(index_t index, yield_function_t yieldFunction) :
parent_t(index, yieldFunction) {}
value_type operator*() {
return parent_t::mYieldFunction(parent_t::mIndex);
}
};
template<typename IndexTy>
struct Range {
public:
typedef IndexTy index_t;
typedef Range<IndexTy> mytype_t;
index_t begin;
index_t end;
};
template<typename ResTy, typename IndexTy>
class GeneratorCollection {
public:
typedef Range<IndexTy> range_t;
typedef IndexTy index_t;
typedef ResTy res_t;
typedef typename yield_function<res_t, index_t>::type yield_function_t;
typedef YieldIterator<ResTy, IndexTy> iterator;
typedef YieldConstIterator<ResTy, IndexTy> const_iterator;
GeneratorCollection(range_t range, const yield_function_t &yieldF) :
mRange(range),
mYieldFunction(yieldF) {}
iterator begin() {
return iterator(mRange.begin, mYieldFunction);
}
iterator end() {
return iterator(mRange.end, mYieldFunction);
}
const_iterator begin() const {
return const_iterator(mRange.begin, mYieldFunction);
}
const_iterator end() const {
return const_iterator(mRange.end, mYieldFunction);
}
private:
range_t mRange;
yield_function_t mYieldFunction;
};
template<typename ResTy, typename IndexTy>
class Generator {
public:
typedef IndexTy index_t;
typedef ResTy res_t;
typedef typename yield_function<res_t, index_t>::type yield_function_t;
typedef Generator<ResTy, IndexTy> mytype_t;
typedef Range<IndexTy> parent_t;
typedef GeneratorCollection<ResTy, IndexTy> finalized_emitter_t;
typedef Range<IndexTy> range_t;
protected:
Generator(range_t range) : mRange(range) {}
public:
static mytype_t on_range(index_t begin, index_t end) {
return mytype_t({ begin, end });
}
finalized_emitter_t yield(yield_function_t f) {
return finalized_emitter_t(mRange, f);
}
protected:
range_t mRange;
};