Sequence generator with custom step size, start value and operation I have created a little generator class to generate number sequences.The intended purpose of this class is to be used with generate_n to populate containers. I would like to know whether there is something which i can do to improve performance or usability or to make the code more generic. It should be possible to compile the code with a c++14 conformant compiler at the moment, but i am open to use any number of c++17 features.
My generator class:

#include &lt;functional&gt;

template&lt;typename Number,
         typename AdvanceOperation = std::plus&lt;Number&gt;&gt;
class sequence_generator
{
  public:
    constexpr sequence_generator(Number start_value = Number{},
                                 Number step_size = Number{1},
                                 AdvanceOperation advancer = AdvanceOperation{})
                                 : current_value{start_value},
                                   step_size{step_size},
                                   advancer{advancer}
    {}
    constexpr auto operator()() -&gt; Number
    {
      return next();
    }
    constexpr auto next() -&gt; Number
    {
      auto tmp = current_value;
      current_value = advancer(current_value, step_size);
      return tmp;
    }
  private:
    Number current_value;
    Number step_size;
    AdvanceOperation advancer;
};

template&lt;typename Number, typename AdvanceOperation=std::plus&lt;Number&gt;&gt;
auto make_sequence_generator(Number start_value, Number step_size,
                             AdvanceOperation advancer)
{
    return sequence_generator&lt;Number, AdvanceOperation&gt;{start_value, step_size,
                                                        advancer};
}


Some use cases:

#include &lt;algorithm&gt;
#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;cassert&gt;

#include "generator.hpp"

int main()
{
  std::vector&lt;int&gt; vector(10);
  std::generate(std::begin(vector), std::end(vector),
                sequence_generator&lt;int&gt;{});
  assert(vector == std::vector&lt;int&gt;({0,1,2,3,4,5,6,7,8,9}));
  std::generate(std::begin(vector), std::end(vector),
                make_sequence_generator(1,2,std::multiplies&lt;&gt;{}));
  assert(vector == std::vector&lt;int&gt;({1,2,4,8,16,32,64,128,256,512}));
}
Generally code looks good. Despite that, there are number of places where it could be improved.

There is no need to specify output type explicitly. I'm not a language lawyer, but return type seems explicit to me. Also, ideone compiler is able to compile it without return type hints.

The behavior of the next is surprising. It returns old value and then advances it. I'd expect it to be vice versa. I guess you wanted to output initial value once, so it is probably a design choice. On top of that, it is probably the most performance draining part of the code.

There is no need to write constexpr on every function. It will mean inline, which itself means bloating size of the executable. Cases where it could be really compile time evaluated are very rare. The deal breaker factor here is advancer function, and if it returns different values on each call it is probably impossible to evaluate it at compile time. I'm excluding possibilities of immense template metaprogramming magic.

I would change interface to use binary operation to advance it. It would be much more customizable. 

Overall I think std::generate_n is more for randomly generated numbers or something alike. People usually use std::iota to fill with increasing values.

Proposal

I propose a very different solution.

The solution will be a generic function named stepping_iota.

template &lt;typename OutputIterator, typename T, typename UnaryAdavanceOp&gt;
void stepping_iota(OutputIterator first, OutputIterator last, T init_value, UnaryAdavanceOp op)


It will call std::iota under the hood, to avoid surprises. But to do that, it will use proxy pattern. Specifications say that it is not required for decltype(*first) and T to match. So we can implement very small proxy, which will have all the needed functionality.

namespace impl_details
{
    template &lt;typename T, typename UnaryAdvanceOp&gt;
    class proxy
    {
        T value;
        UnaryAdvanceOp op;
    public:
        proxy(T init_value, UnaryAdvanceOp op_) :
            value(init_value),
            op(op_)
        {}

        operator T()
        {
            return value;
        }

        T operator++()
        {
            value = op(value);
            return value;
        }

        T operator++(int)
        {
            T old = value;
            value = op(value);
            return old;
        }
    };
}


I've written post increment for the sake of symmetry.

Then the stepping_iota will construct the proxy and pass it to std::iota:

impl_details::proxy&lt;T, UnaryAdavanceOp&gt; p(init_value, op);
std::iota(first, last, p);


Despite the function has a few parameters, it is customizable and easy to use with lambdas. It uses unary operation, which is common and used in functions such as std::transform.

Complete example:

#include &lt;numeric&gt;

namespace impl_details
{
    template &lt;typename T, typename UnaryAdvanceOp&gt;
    class proxy
    {
        T value;
        UnaryAdvanceOp op;
    public:
        proxy(T init_value, UnaryAdvanceOp op_) :
            value(init_value),
            op(op_)
        {

        }

        operator T()
        {
            return value;
        }

        T operator++()
        {
            value = op(value);
            return value;
        }

        T operator++(int)
        {
            T old = value;
            value = op(value);
            return old;
        }
    };
}

template &lt;typename OutputIterator, typename T, typename UnaryAdavanceOp&gt;
void stepping_iota(OutputIterator first, OutputIterator last, T init_value, UnaryAdavanceOp op)
{
    impl_details::proxy&lt;T, UnaryAdavanceOp&gt; p(init_value, op);
    std::iota(first, last, p);
}

#include &lt;vector&gt;
#include &lt;iostream&gt;

int main()
{
    std::vector&lt;int&gt; v(10'000);


    stepping_iota(v.begin(), v.end(), 0, [](const int&amp; x) { return x + 1; });

    for (const auto&amp; elem : v)
    {
        std::cout &lt;&lt; elem &lt;&lt; ' ';
    }
}


In C++17 you will be able to write:

impl_details::proxy p( init_value, op );