简体   繁体   中英

How can implement my custom ranged for loop?

I do really like Ranged-based-for-loop which is supported by C++11 and above. I'd like for some understanding reason to simulate it. Here is an example:

// 1
//#define ranged_for(X, T) \
//  for (std::vector<int>::iterator beg{ T.begin() },\
//      end{ T.end() }; beg != end; X = *beg, ++beg)\

// 2
//#define ranged_for(X, T) \
//  for (std::vector<int>::iterator beg{ T.begin() },\
//      end{ T.end() }; beg != end; ++beg, X = *beg)\

// 3
#define ranged_for(X, T) \
    for (std::vector<int>::iterator beg{ T.begin() },\
        end{ T.end() }; beg != end; ++beg)\
            X = *beg, 



int main(){
    std::vector<int> data{75, 435, 6578, 92, 123};

    auto i{ 0 };
    ranged_for(i, data)
        std::cout << i << std::endl;

    std::cout << std::endl;
    std::cin.get();
    return 0;
}

As you can see above the first macro doesn't get the first element 75 but instead the value 0 and the last one is not there. That is because I guess in my main I print x before assigning it in the post-iteration part of the loop.

  • The second macro crashes the program that is because i think de-referencing the last node (sentry node).

  • The third works fine but as you can see after the macro expansion I'll get:

     i = *beg, std::cout << i << std::endl; 

That is because the line above is treated as a single statement. Is there a better way and explanation. Thank you all good dudes!.

Why do you oppose C++ ranged based for loops so much?

int i;
ranged_for(i, data)
    // ...

vs.

for(int i : data)

You needed to predeclare i so far. You cannot use references this way! Now let's imagine we manage to get it cleverer:

ranged_for(int& i, data)

vs.

for(int& i : data)

What did you gain? Using a comma instead of a colon??? Honestly, that's not worth the effort. A scenario more interesing to consider:

auto i = data.end();
for(auto j = data.begin(); j != data.end(); ++j)
{
    if(someCondition)
        i = j;
}
if(i != data.end())
{
    // ...
}

OK, that's rather rare already. In many, if not most cases you can move the outer if's body into the inner one adding a break instruction at the end. And in these few cases you still cannot do so - well, then I'd live with the explicit iterator loop – it's not that heavy to write...

This should work for both single line and multiline scopes:

#define ranged_for(X, T) \
    for(auto it=std::begin(T); it!=std::end(T) && (X=*it,true); ++it)

Or a version that can be used to auto deduce the type X should be, but it requires an additional macro:

#define ranged_for(X, T) \
    {decltype(T)::value_type X; for(auto it=std::begin(T); it!=std::end(T) && (X=*it,true); ++it) {

#define range_end }}

int main(){
    std::vector<int> data{75, 435, 6578, 92, 123};

    ranged_for(i, data)
        std::cout << i << std::endl;
    range_end
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM