|
Boost Users : |
Subject: Re: [Boost-users] [range] questions about documentation and usage
From: Nathan Ridge (zeratul976_at_[hidden])
Date: 2012-11-02 03:41:04
>>> This effectively means that the "Valid
Expressions" for
>>> SinglePassRange part of the documenation should
read:
>>>
>>> a.begin()
>>> a.end()
>>>
>>> Doesn't it. I would be interested to know if I got this
wrong.
>>
>> Nope.
>>
>> Suppose I have a third-party
library with a class named Vector
>> which has methods named Begin() and
End() rather than begin() and
>> end(). I can't change Vector, but I'd
still like to use it as a
>> SinglePassRange. Boost.Range allows me to do
that, by overloading
>> range_begin() and range_end() in the namespace of
Vector (so that
>> boost::begin() and boost::end() finds them by ADL) as
described in
>> [1].
>>
>> namespace
namespace_of_Vector
>> {
>> Vector::Iterator
range_begin(Vector& v) { return v.Begin(); }
>>
Vector::Iterator range_end(Vector& v) { return v.End();
}
>> // overloads for const Vector&
>>
}
>>
>> Now if v is of type Vector, boost::begin(v) and boost::end(v)
will be
>> valid expressions, but v.begin() and v.end() will not.
>
> Of course you can do this. But looking at the
documenation
> you wouldn't expect copy(std::vector<int>, 0) to
compile without
> error. In fact, looking at the documentation you
would conclude
> that you have to do this - when in fact you don't.
>
> The concept classes of Boost.Range test success
for
> something like vector<int> which suggests that a
container
> is a range. Although it's technically correct within
the confines
> of boost.range - it's extremely unintuitive and
confusing.
>
> For example, it's not at all obvious
>
> int x[10]
> boost::find(x, 0); should compile or
not.
>
>> So this extra layer allows us to adapt third-party types that we
have
>> no control over to model Boost.Range concepts such as
SinglePassRange.
>
> I can see that by looking at the implementation but it's
not clear from
> looking at the documentation. The fact that there is
an extra layer
> is sort of hidden from the person using the
library.
This is documented both in the Introduction page of the documentation:
"This library therefore provides the means to adapt standard-like containers,
null terminated strings, std::pairs of iterators, and raw arrays (and more),
such that the same generic code can work with them all. The basic idea is
to add another layer of indirection using metafunctions and free-standing
functions so syntactic and/or semantic differences can be removed." [1]
and in the page that documents Method 1 of making types model ranges:
"The primary templates in this library are implemented such that standard
containers will work automatically and so will boost::array. Below is given
an overview of which member functions and member types a class must
specify to be useable as a certain Range concept." [2]
If you believe there are additional places in the documentation where
this should be mentioned, I am sure the Boost.Range maintainers will
be happy to accept a patch to the documentation.
>>> b) I see the template
iterator_range<ForwardTraversalIterator> -
>>>
>>> which
seem to be to in an instance of what the ForwardRangeConcept
>>> should
be.
>>
>> I'm not sure I understand what the question/problem here
is.
>> Could you elaborate?
>
> It just illustrates the source of the
confusion.
iterator_range<ForwardTraversalIterator>
> is a direct implementation of
ForwardTransversalRange> and sort of what I exect to see.
> It's not clear how a std::vector gets "transformed" -
(Please don't explain
> it to me, I've seen how it works). This intermediate
transformation>
> goes directly from vector->ForwardTransversalRange
without
> passing through and interator_range.
>
> It's all very confusing, an unintuitive which makes it
much
> harder to figure out how to use it than it should
be.
I don't see what iterator_range has to do with vector or with "transforming" anything.
Indeed, the documentation for iterator_range doesn't even mention the words
"vector" or "transform". *You* are confusing yourself by trying to draw a connection
where there isn't one.
iterator_range is simply a utility for when you have a pair of iterators that delimit
a range and you want to package them up as a range, and this pair of iterators
is not a begin/end pair for an object that is already a range. For example, if you
had a vector with 5 elements:
vector<int> v = {1, 2, 3, 4, 5};
and you wanted a range representing the last 3 elements, a convenient way
to write down such a range would be:
make_iterator_range(v.begin() + 2, v.end())
> d) I forgot to add this. The exposition of each
function, template etc, could
> benefit by including a small example. This is common
practice
> among other similar libraries. It is generally very
helpful.
Agreed. Once again, I'm sure the maintainers would welcome patches.
Regards,
Nate
[1] http://www.boost.org/doc/libs/1_51_0/libs/range/doc/html/range/introduction.html
[2] http://www.boost.org/doc/libs/1_51_0/libs/range/doc/html/range/reference/extending/method_1.html
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net