Skip to content

Range-based for loop

cpppatterns Range iteration

NOTE: 这篇文章,对range-based for loop的介绍是更加易懂的。

The range-based for loop provides a simple syntax for iterating over elements of a range without using iterators or indices. It supports arrays, types that provide begin and end member functions, and types for which begin and end functions are found via argument-dependent lookup.

cppreference Range-based for loop

begin_expr and end_expr are defined as follows:

NOTE: 如何实现?

Example

stackoverflow Is there a range class in C++11 for use with range based for loops?

#include <iostream>

template<long int T_begin, long int T_end>
class range_class
{
public:
    class iterator
    {
        friend class range_class;
        public:
        long int operator *() const
        {
            return i_;
        }
        const iterator &operator ++()
        {
            ++i_;
            return *this;
        }
        iterator operator ++(int)
        {
            iterator copy(*this);
            ++i_;
            return copy;
        }

        bool operator ==(const iterator &other) const
                {
            return i_ == other.i_;
        }
        bool operator !=(const iterator &other) const
                {
            return i_ != other.i_;
        }

    protected:
        iterator(long int start)
                : i_(start)
        {
        }

    private:
        unsigned long i_;
    };

    iterator begin() const
    {
        return iterator(T_begin);
    }
    iterator end() const
    {
        return iterator(T_end);
    }
};

template<long int T_begin, long int T_end>
const range_class<T_begin, T_end>
range()
{
    return range_class<T_begin, T_end>();
}

int main()
{
    for (auto i : range<0, 10>())
    {
        std::cout << i << std::endl;
    }
}
// g++ --std=c++11 test.cpp

输出如下:

0
1
2
3
4
5
6
7
8
9

Example

https://stackoverflow.com/a/7185723

#include <iostream>
#include <sstream>

class range
{
public:
    class iterator
    {
        friend class range;
        public:
        long int operator *() const
        {
            return i_;
        }
        const iterator &operator ++()
        {
            ++i_;
            return *this;
        }
        iterator operator ++(int)
        {
            iterator copy(*this);
            ++i_;
            return copy;
        }

        bool operator ==(const iterator &other) const
                {
            return i_ == other.i_;
        }
        bool operator !=(const iterator &other) const
                {
            return i_ != other.i_;
        }

    protected:
        iterator(long int start)
                : i_(start)
        {
        }

    private:
        unsigned long i_;
    };

    iterator begin() const
    {
        return begin_;
    }
    iterator end() const
    {
        return end_;
    }
    range(long int begin, long int end)
            : begin_(begin), end_(end)
    {
    }
private:
    iterator begin_;
    iterator end_;
};

int main()
{
    int m, n;
    std::istringstream in("10 20");
    if (in >> m >> n) //using in, because std::cin cannot be used at coliru.
    {
        if (m > n)
        {
            std::swap(m, n);
        }
        for (auto i : range(m, n))
        {
            std::cout << i << " ";
        }
    }
    else
    {
        std::cout << "invalid input";
    }
}
// g++ --std=c++11 test.cpp

Example

https://stackoverflow.com/a/8578101

#include <iostream>
using namespace std;

struct r_iterator
{
    long int value;
    r_iterator(long int _v)
            : value(_v)
    {
    }
    operator long int() const
    {
        return value;
    }
    operator long int&()
    {
        return value;
    }
    long int operator*() const
    {
        return value;
    }
};
template<long int _begin, long int _end>
struct range
{
    static r_iterator begin()
    {
        return _begin;
    }
    static r_iterator end()
    {
        return _end;
    }
};
int main()
{
    for (auto i : range<0, 10>())
    {
        cout << i << endl;
    }
    return 0;
}
// g++ --std=c++11 test.cpp

Example:

stackoverflow Viewing a raw pointer as a range in range-based for-loop # A

A workaround for what you want to do is just make a simple wrapper:

template <typename T> 
struct PtrWrapper {
    T* p;
    T* begin() const { return p; }
    T* end() const { return p ? p+1 : nullptr; }
};

for (double& d : PtrWrapper<double>{dptr}) { .. }

geeksforgeeks Reversed Range-based for loop in C++ with Examples

// C++ program for reverse 
// range-based for loop 
#include <bits/stdc++.h> 

// For reversing range based loop 
#include <boost/range/adaptor/reversed.hpp> 
using namespace std; 

// Driver Code 
int main() 
{ 
    string s = "geeksforgeeks"; 

    int y[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; 

    vector<int> v1{ 1, 2, 3, 4, 5, 6, 7, 8 }; 

    // Reverse range-based for loop 
    // to reverse string 
    for (auto x : boost::adaptors::reverse(s)) 
        cout << x << " "; 
    cout << endl; 

    // Reverse range-based for loop 
    // to reverse array 
    for (auto x : boost::adaptors::reverse(y)) 
        cout << x << " "; 
    cout << endl; 

    // Reverse range-based for loop 
    // to reverse vector 
    for (auto x : boost::adaptors::reverse(v1)) 
        cout << x << " "; 
    cout << endl; 

    return 0; 
}