Reputation: 13928
In boost directory_iterator example - how to list directory files not recursive (see this answer) is the sample code
#include <boost/filesystem.hpp>
#include <boost/range/iterator_range.hpp>
#include <iostream>
...
using namespace boost::filesystem;
for(auto& entry : boost::make_iterator_range(directory_iterator(p), {}))
{
std::cout << entry << "\n";
}
(p
is of type boost::filesystem::path
.)
Upon looking at the documentation for make_iterator_range
, I think the constructor being called is this one:
template< class ForwardTraversalIterator >
iterator_range< ForwardTraversalIterator >
make_iterator_range( ForwardTraversalIterator Begin,
ForwardTraversalIterator End );
If I'm right, then the second argument passed in the code example above, {}
, seems to correspond to the end of whatever container is invisibly iterated over by the directory_iterator
.
I've never seen this before.
Is it possible to construct the end
iterator just by value-constructing such an iterator from the empty initializer list {}
? (Am I even phrasing this properly?)
I wouldn't mind having someone spell out what is going on under the hood, given that the type of the iterator so constructed must match the type of the first iterator (directory_iterator(p)
). (Is template argument deduction going on here?)
Upvotes: 4
Views: 395
Reputation: 385375
Yes, it's valid.
There's no template argument deduction beyond that which you already usually invoke: your first argument is of type directory_iterator
, so the function is instantiated as such.
Following on from that, templates aside, now you are calling a function that takes two directory_iterators
: the {}
can only initialise a directory_iterator
at that point, as that's what your function [template instance] takes. Hence, in this case, writing {}
is functionally equivalent to writing directory_iterator{}
.
If the directory_iterator
could not be constructed from {}
, your program would not compile.
Upvotes: 3
Reputation: 63946
Here are the various overloads for boost::make_iterator_range
:
template< class ForwardTraversalIterator >
iterator_range< ForwardTraversalIterator >
make_iterator_range( ForwardTraversalIterator Begin,
ForwardTraversalIterator End );
template< class ForwardRange >
iterator_range< typename range_iterator<ForwardRange>::type >
make_iterator_range( ForwardRange& r );
template< class ForwardRange >
iterator_range< typename range_iterator<const ForwardRange>::type >
make_iterator_range( const ForwardRange& r );
template< class Range >
iterator_range< typename range_iterator<Range>::type >
make_iterator_range( Range& r,
typename range_difference<Range>::type advance_begin,
typename range_difference<Range>::type advance_end );
template< class Range >
iterator_range< typename range_iterator<const Range>::type >
make_iterator_range( const Range& r,
typename range_difference<const Range>::type advance_begin,
typename range_difference<const Range>::type advance_end );
Since your code has already specified that the first parameter is of type
directory_iterator
, the only valid type for the second parameter is directory_iterator
. It's unambiguous.
Therefore, the type doesn't need to be specified. {}
is synonymous with directory_iterator{}
, which is also synonymous with directory_iterator()
.
Upvotes: 1