Подтвердить что ты не робот

Std:: iota очень ограничен

Из мира Python я считаю, что функция std::iota очень ограничена. Почему интерфейс ограничен, чтобы не принимать никаких UnaryFunction?

Например, я могу преобразовать

>>> x = range(0, 10)

в

std::vector<int> x(10);
std::iota(std::begin(x), std::end(x), 0);

Но как это сделать:

>>> x = range(0,20,2)

или даже

>>> x = range(10,0,-1)

Я знаю, что это тривиально написать одну из таких функций или использовать Boost, но я подумал, что комитет С++ должен тщательно подобрать этот дизайн. Так ясно, что я пропускаю что-то из С++ 11.

4b9b3361

Ответ 1

Но как это сделать:

x = range(0,20,2)

В качестве альтернативы std::generate() (см. другой ответ) вы можете предоставить свою унарную функцию std::iota(), ее просто нужно называть operator++():

#include <iostream>
#include <functional>
#include <numeric>
#include <vector>

template<class T>
struct IotaWrapper
{
    typedef T type;
    typedef std::function<type(const type&)> IncrFunction;

    type value;
    IncrFunction incrFunction;

    IotaWrapper() = delete;
    IotaWrapper(const type& n, const IncrFunction& incrFunction) : value(n), incrFunction(incrFunction) {};

    operator type() { return value; }
    IotaWrapper& operator++() { value = incrFunction(value); return *this; }
};

int main()
{
    IotaWrapper<int> n(0, [](const int& n){ return n+2; });
    std::vector<int> v(10);
    std::iota(v.begin(), v.end(), n);

    for (auto i : v)
        std::cout << i << ' ';
    std::cout << std::endl;
}

Выход: 0 2 4 6 8 10 12 14 16 18

Демо


Вот идея о том, как можно реализовать Range():

struct Range
{
    template<class Value, class Incr>
    std::vector<Value> operator()(const Value& first, const Value& last, const Incr& increment)
    {
        IotaWrapper<Value> iota(first, [=](const int& n){ return n+increment; });
        std::vector<Value> result((last - first) / increment);
        std::iota(result.begin(), result.end(), iota);
        return result;
    }
};

Демо

Ответ 2

как насчет std::generate?

int n = -2;
std::generate(x.begin(), x.end(), [&n]{ return n+=2; }); 
int n = 10;
std::generate(x.begin(), x.end(), [&n]{ return n--;})