2016-11-01 8 views
0

PythonのようにC++でサイクルを行う最も簡単な方法は何ですか?PythonのようなC++でのサイクル

for i in range(10): #or range(4, 10, 2) etc 
    foo(i) 

私はこの

for(auto i: range(10)) //or range(4, 10, 2) or range(0.5, 1.0, 0.1) etc 
    foo(i); 

ではなく、このようなような単純なものと一行意味:もちろん

std::vector<int> v(10); 
std::iota(begin(v), end(v), 0); 
for(auto i: v) { 
    foo(i); 
} 

またはこの

for(auto i: []{vector<size_t> v(10); return iota(begin(v), end(v), 0), v;}()) { 
    foo(i);   
} 

、それはあるがこれらの例を使用するのが難しくないか、ちょうどfor(;;)しかし、私はそれを簡潔かつ簡潔にpythonで行う方法があることを願っています。

+2

C++には、これについての省略表現はありません。伝統的な 'for(i = 0; i <10; i ++)を使用してください。 – Barmar

+0

_ @ NikBond_複製物からの解決があなたのために十分簡単であることを願っています。ちょうど10秒のGoogleクエリだった。 –

+0

@Barmarあなたは毎日何か新しいことを学びます;) –

答えて

1

A Pythonのようなrange概念は、このように、アウト・オブ・ボックスに提供されていませんが、簡単なイテレータを使用して独自のRangeクラスをロールバックできます。

#include <iostream> 

template <typename T> 
class Range 
{ 
public: 
    class iterator 
    { 
    public: 
    explicit iterator(T val, T stop, T step) : m_val(val), m_stop(stop), m_step(step) { } 
    iterator& operator ++() 
    { 
     m_val += m_step; 
     if ((m_step > 0 && m_val >= m_stop) || 
      (m_step < 0 && m_val <= m_stop)) 
     { 
     m_val = m_stop; 
     } 
     return *this; 
    } 
    iterator operator ++ (int) { iterator retval = *this; ++(*this); return retval; } 
    bool operator == (iterator other) const {return m_val == other.m_val;} 
    bool operator != (iterator other) const {return !(*this == other);} 
    T operator *() const { return m_val; } 
    private: 
    T m_val, m_stop, m_step; 
    }; 

    explicit Range(T stop) 
    : m_start(0), m_stop(stop), m_step(1) 
    { } 

    explicit Range(T start, T stop, T step = 1) 
    : m_start(start), m_stop(stop), m_step(step) 
    { } 

    iterator begin() const { return iterator(m_start, m_stop, m_step); } 
    iterator end() const { return iterator(m_stop, m_stop, m_step); } 

private: 
    T m_start, m_stop, m_step; 
}; 

template <typename T> 
Range<T> range(T stop) { return Range<T>(stop); } 

template <typename T> 
Range<T> range(T start, T stop, T step = 1) { return Range<T>(start, stop, step); } 

int main() 
{ 
    for (auto i : range(10)) { std::cout << " " << i; } 
    std::cout << std::endl; 
    for (auto i : range(4, 10, 2)) { std::cout << " " << i; } 
    std::cout << std::endl; 
    for (auto i : range(0.5, 1.0, 0.1)) { std::cout << " " << i; } 
    std::cout << std::endl; 
} 

レンジ・支援するためにfor、反復子タイプ、そしてbegin()/end()関数がその仕事をします。 (もちろん、上記の私の実装はすばやく汚れていて、おそらく改善される可能性があります)

あなたは自分のクラスを動かすことはありませんが、いったん使用してしまうと、Pythonのアプローチとよく似ています:

for (auto i : range(stop)) { ... } 
for (auto i : range(start, stop, step)) { ... } 

出力例(see live version here):あなたが唯一の整数範囲を必要とする場合

$ g++ -std=c++11 -o test test.cpp && ./test 
0 1 2 3 4 5 6 7 8 9 
4 6 8 
0.5 0.6 0.7 0.8 0.9 1 

、あなたもboost::irange(リマインダー用Yakkのおかげで)使用することができます。

+0

浮動小数点1は悪い考えです。あなたが '> ='でセンチナルを使用していない限りです。ああ、イテレータにm_stopを保存してお待ちください! – Yakk

+0

'm_step'を別々にテンプレート化することで、ステートレスなインクリメント・バイ・ケースを可能にして効率を向上させることができます。私は 'm_stop'について心配しています。私は浮動小数点と階段のためにその使用を得るが、... – Yakk

+0

'boost;:irange'と記述するとこの答えが改善されます。 – Yakk

関連する問題