Dimitar Mirchev Dimitar Mirchev - 3 months ago 20
C++ Question

How the new range-based for loop in C++17 helps Ranges TS?

The committee changed the range-based for loop from:


  • C++11:

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

  • to C++17 :

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



And people said that this will make implementing Ranges TS easier. Can you give me some examples?

Answer

The new specification allows __begin and __end to be of different type, as long as __end can be compared to __begin for inequality. __end doesn't even need to be an iterator and can be a predicate. Here is a silly example with a struct defining begin and end members, the latter being a predicate instead of an iterator:

#include <iostream>
#include <string>

// a struct to get the first word of a string

struct FirstWord {
    std::string data;

    // declare a predicate to make ' ' a string ender

    struct EndOfString {
        bool operator()(std::string::iterator it) { return (*it) != '\0' && (*it) != ' '; }
    };

    std::string::iterator begin() { return data.begin(); }
    EndOfString end() { return EndOfString(); }
};

// declare the comparison operator

bool operator!=(std::string::iterator it, FirstWord::EndOfString p) { return p(it); }

// test

int main() {
    for (auto c : {"Hello World !!!"})
        std::cout << c;
    std::cout << std::endl; // print "Hello World !!!"

    for (auto c : FirstWord{"Hello World !!!"}) // works with gcc with C++17 enabled
        std::cout << c;
    std::cout << std::endl; // print "Hello"
}