Poeta Kodu
Poeta Kodu

Reputation: 1150

How does range-for iterator class work?

I do know, how this code works:

std::vector<int> sth;
for (auto const & elem : sth) { }

However, this code is mysterious for me:

namespace fs = std::filesystem;
for(auto & file : fs::directory_iterator("some/path"))
    std::cout << file << std::endl;

How does this class (std::filesystem::directory_iterator) work, that it enable me iterate through entire container? As far as I know, the range-for works like this:

// given "container"
for(auto it = std::begin(container); it != std::end(container); it++)
{
}

How it is possible in case of passing directory_iterator as container here?

Upvotes: 1

Views: 83

Answers (1)

Steve Lorimer
Steve Lorimer

Reputation: 28659

Range-based for is syntactic sugar for a traditional for loop

All it does is execute a for loop over a range.

It is a more readable equivalent to the traditional for loop operating over a range of values, such as all elements in a container.

Under the hood, the compiler will convert a range-based for loop into something like the following:

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

begin_expr and end_expr are defined as follows:

  • If range_expression is an expression of array type, then begin_expr is __range and end_expr is (__range + __bound), where __bound is the number of elements in the array (if the array has unknown size or is of an incomplete type, the program is ill-formed)

  • If range_expression is an expression of a class type C that has a member named begin and/or a member named end (regardless of the type or accessibility of such member), then begin_expr is __range.begin() and end_expr is __range.end();

  • Otherwise, begin_expr is begin(__range) and end_expr is end(__range), which are found via argument-dependent lookup (non-ADL lookup is not performed).

std::filesystem::directory_iterator

In the case of directory_iterator it is the third option above, in that it has begin and end non-member functions which allows it to be used in range-based for loops.

Upvotes: 1

Related Questions