C ++ 11 for loop, and the implementation of the Range class, forrange

Source: Internet
Author: User

C ++ 11 for loop, and the implementation of the Range class, forrange

C ++ 11 supports the range-based for loop. This is a convenient feature that saves a lot of code. The following code can easily traverse the elements in the vector and print them out:

12345678 std::vector<int> int_vec;int_vec.push_back(1);int_vec.push_back(2);// If You Want To modify the element in int_vec, declare variable x as int &.for (int x: int_vec){    std::cout << x << endl;}

Objects that can be traversed include:

  • Array. (Excluding pointers)
  • Defines the begin () and end () methods, and returns the Class Object of the iterator returned by this method. (All containers in STL can)

(For the traversal of dynamically generated arrays, the Range class described below can save a lot of code)

See the http://en.cppreference.com/w/cpp/language/range-for,

Statementfor (Range_declaration:Range_expression)Loop_statement

It is equivalent to the following statement:

123456789 {     auto && __range = range_expression ;     for (auto __begin = begin_expr,             __end = end_expr;            __begin != __end; ++__begin) {        range_declaration = *__begin;     loop_statement    } }

For class objects that can be traversed, __begin and _ end are generated by the begin () and end () Methods of the class respectively. The _ range variable references the right value. If range_expression returns the right value, it will analyze the structure after the loop ends.

In this way, C ++ 11 finally supports the Traversal method supported by modern programming languages. However, neither the syntax nor the standard library supportsNumberFor example, in the for I in xrange () Statement in python, x will consecutively take the value in. (The Boost library has an irange class that can meet this requirement, but my implementation will be discussed below)

The most direct method is to write a function and return a vector <int> object. Its element is the value from begin to end. In this way, such an object must be constructed for each loop, which is a little slow.

From the standard perspective, if a class must support such traversal, at leastBegin () and end ()Method. In the initialization Part Of The for loop, after the two methods are called, nothing happens to this class --It's all about the iterator.. So naturally, the iterator is used up and down. This iterator must support three operations:! =, Prefix ++, unreference. No. If the iterator is an int value, _ begin the above loop! The =__ end; ++ _ begin statement is a very natural implementation. The current goal is simple: This "iterator" does not traverse every element in the container, but isEncapsulation of simple int values. This number is returned for its unreferenced operation, and the comparison and auto-increment operations operate on this number.

Once you have an idea, it is easy to implement it. First, define a quasi-iterator FakeIter, which encapsulates a value and reloads the necessary operators.

12345678910111213141516171819202122232425262728 class FakeIter{    typedef long _VType;  // The value type is long. Of course, you can also write a template.public:     explicit FakeIter(_VType val)        :value_(val){}     bool operator != (const FakeIter& other) const    {        return (this->GetValue()) != (other.GetValue());    }    _VType operator* () const    {        return GetValue();    }    const FakeIter& operator++ ()    {        ++value_;        return *this;    }private:    _VType GetValue() const    {        return value_;    }    _VType value_;};

The implementation of the "Container" class is simpler: implement the begin () and end () methods, and return the above FakeIter. Some cout statements are added to the methods in the class, so that you can better understand the calling process of specific methods during cyclic execution. You can delete them in actual use.

12345678910111213141516171819202122232425262728 class Range{    typedef long _VType;    // Similarly, you can create a template, but it is not convenient to use.public:    Range (_VType begin_v, _VType end_v)        :begin_value_(begin_v), end_value_(end_v)    {        cout<<"Range::Range()"<<endl;    }    ~Range()    {        cout<<"Range::~Range()"<<endl;    }     FakeIter begin () const    {        cout<<"Range::begin()"<<endl;        return FakeIter(begin_value_);    }    FakeIter end () const    {        cout<<"Range::end()"<<endl;        return FakeIter(end_value_ );    }private:    _VType begin_value_;    _VType end_value_;};

Okay. Try this product. It's useless:

12345 for (auto x: Range(1,5)){    std::cout<<x<<endl;}std::cout<<"Loop end"<<endl;

Output in vs2012 and clang is as follows:

Range::Range() 
Range::begin() 
Range::end() 




Range::~Range() 
Loop end

Well, if you comment out the output statements that affect the line of sight, it seems to be usable. Now, if we want to traverse an array generated by new, we only need to use this array to set a subscript, and the world will be quiet.

But what about the step size! Well, it seems that I have no such requirement yet. However, it is easy to implement: you can modify the FakeIter class. You can add a member indicating the step size and then modify the auto-increment operation. Furthermore, you can add a generator method to become a more common generator. It is convenient to use with the C ++ 11 lambda operator.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.