У меня есть вопрос, который, скорее всего, был задан раньше, потому что я думаю, что я хочу, это то, чего захочет значительная часть людей. Однако я не мог придумать какой-либо способ выразить это, что бы вернуть то, что я хотел в поиске (не Google, не здесь). Поэтому, возможно, ответ здесь - это всего лишь один термин, используемый для описания того, что я имею в виду.
Что я хочу реализовать, это примерно то, что примерно следующее:
-
Он может принимать конструктор/класс functor и генерировать последовательность значений для упомянутого функтора, основанного на функторной функции. Должно быть возможно использовать функтор с состоянием, т.е. Должно быть возможно создать экземпляр функтора в состоянии a и запустить его до тех пор, пока он не окажется в состоянии b, генерируя диапазон значений {f (a), f (a + 1),..., f (b)}, где f (a + 1) представляет следующий элемент в ряду, представленный f.
-
Он ведет себя как итератор, то есть он может быть передан вместо итератора, например. для заполнения вектора со значениями.
Я думаю, что это имя должно быть генератором или генерировать итератор, потому что это то, что он делает, но мне очень не удалось найти что-то с этим термином. Я написал свою собственную реализацию, но у нее есть свои проблемы, и я хотел спросить, есть ли такая вещь, прежде чем прикладывать к ней какие-либо дополнительные усилия.
Чтобы сэкономить вам работу по вставке всего последующего кода на случай, если вы хотите попробовать это, я положил его на ideone. Я думаю, что после запуска кода довольно ясно, что он делает.
Моя текущая реализация выглядит так (fyi это сокращенная версия, где некоторые вещи вроде - и - отсутствуют, так что да, я их реализую, и, таким образом, она может работать хотя бы как двунаправленный итератор. [], поэтому я подумал о том, чтобы сделать его random_access.):
template <class F>
class generator{
public:
//typedefs required for iterator-use
typedef typename F::value_type value_type;
typedef typename F::step_type step_type;
typedef value_type * pointer;
typedef value_type & reference;
typedef typename F::size_type size_type;
typedef typename F::difference_type difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
generator(value_type init, step_type step) : t(init), step(step){}
generator<F> &operator++() {
t += step; return *this;
}
generator<F> &
operator+=(size_type n)
{
t += n * step;
return *this;
}
generator<F>
operator+(size_type n)
{
return generator(*this) += n;
}
value_type operator*() const {
return f(t);
}
value_type operator*() const {
return f(t);
}
friend bool operator==(const generator<F> &lhs, const generator<F> &rhs){
return lhs.t == rhs.t;
}
friend bool operator!=(const generator<F> &lhs, const generator<F> &rhs){
return !(lhs == rhs);
}
private:
value_type t;
value_type step;
F f;
};
Я использую другой шаблон, чтобы максимально упростить typedef:
template <typename T>
struct simple_generator_function
{
typedef T value_type;
typedef T step_type;
typedef T difference_type;
typedef size_t size_type;
};
Прямо сейчас эти два работают вместе с конкретным "генератором" следующим образом:
template <typename T>
struct square_generator : public simple_generator_function<T> {
T operator()(T t) const{
return t * t;
}
};
int main(void) {
using int_sqg = generator<square_generator<int>>;
//starting at initial value 1 take steps of size 4
int_sqg gen(1, 1);
//fill with all before inital + n * step
vector<int> v(gen, gen+10);
copy(begin(v), end(v), ostream_iterator<int>(cout, ","));
cout << '\n';
}
Короче говоря: есть ли дополнительная или другая библиотека, которая предлагает это несколько надёжным образом и как называется такой итератор /functor -mix вообще?
ИЗМЕНИТЬ 1:
Я думаю, что любое решение в лучшем случае может быть InputIterator, потому что, насколько я исследовал его, все остальные итераторы должны были бы вернуть ссылку из оператор *(), о котором в данном случае не может быть и речи. Скорее всего, дело сводится к написанию шаблона, который преобразует обычный функтор в InputIterator.
Статус: ответы до сих пор хороши, но я некоторое время думал об этом, прежде чем спрашивать, и я подумал о подобных решениях, поэтому на мой вопрос не ответил. Я обновил требование 1.) - надеюсь, - более четко отразить то, что я хочу. Если ничего из этого не произойдет, я, вероятно, попытаюсь уточнить мой текущий код в более стабильную версию и поместить ее в github.
ИЗМЕНИТЬ 2 (Конец Баунти):
Несмотря на то, что я не полностью удовлетворен решением, boost:: irange в сочетании с boost:: преобразуется, поскольку предлагаемый ectamur подходит ближе всего к тому, что я хочу, поэтому я дам ему щедрость.