2015-12-31 5 views
13

Pythonワールドから来て、私は関数std::iotaが非常に限られていることがわかります。なぜインタフェースはUnaryFunctionを取らないように制限されていますか?std :: iotaは非常に限定されています

たとえば私は

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

>>> x = range(0, 10) 

変換することができますしかし、一つは何だろうか。

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

あるいは

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

このような関数を書いたり、Boostを使うのは簡単なことですが、私はC++委員会が注意してこの設計を選んだに違いないと思いました。だから、私はC++ 11から何かを見逃しています。

+1

::変換する'もしあなたがベクトル上で他の操作をしたいならば。 –

+2

参照してくださいhttp://stackoverflow.com/q/1977339/2301450 – vaultah

+3

std :: generateを見てくださいが、要点は、C++の本当にエレガントな標準ライブラリソリューションがまだないことです。 – MikeMB

答えて

11

しかし、どのように1はするだろう:std::generate()に代わり

x = range(0,20,2) 

を(他の回答を参照してください)、あなたは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

Demo


ここでは、1つのRange()を実装する方法のアイデアです:

あなたは `のstdを使用することができます
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; 
    } 
}; 

Demo

20

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--;}) 
+0

しかしこれは問題の問題を解決するかもしれません、私は著者が 'std :: iota'のようなものに' std :: iota'(std :: begin(x)、std :: end(x)、0 、2) '2'は反復のステップです - なぜC++ 11にはそれがないのでしょうか?だから私の意見では、この問題はC++の標準的なコミットメントよりも重要です。 –

関連する問題