Boost logo

Boost Users :

Subject: Re: [Boost-users] [Range] invalid initialization of non-const type with adaptors
From: Neil Groves (neil_at_[hidden])
Date: 2010-05-10 08:20:49


On Mon, May 10, 2010 at 2:35 AM, Denis Taniguchi <taniguchi_at_[hidden]>wrote:

> Hi,
>
> I was trying to compile the following simple piece of code:
>
> #include <boost/range/algorithm.hpp>
> #include <boost/range/adaptors.hpp>
>
> #include <vector>
>
> int main(int argc, char *argv[])
> {
> std::vector<int> vec(10);
> boost::fill(vec | boost::adaptors::reversed, 1);
>
> return 0;
> }
>
> But I get the following erros with gcc (Ubuntu 4.3.3-5ubuntu4) 4.3.3:
> Am I missing something here?
>
>
The reason this will not compile is that 'vec | boost::adaptors::reversed'
returns an unnamed temporary which is then attempted to be passed to the
fill function. On many versions of Visual C++ this actually will compile and
work as you intended due to a language extension, but this is non-standard.

This can't easily be remedied since the Range Concept is non-copyable, and
we obviously can't pass a const reference as the target to the fill
algorithm. Making the Range Concept cheaply copyable would mean that the
standard containers were no longer a model of the Range Concepts. I am
currently investigating extending the sub_range into some new Range concepts
that would integrate Alexandrescu's work into Boost.Range nicely. These
sub-ranges would have to be copyable with constant-time complexity and
therefore would enable the fill function to be written to take the sub-range
by value. This would make your code compile. This work, however is very much
in the experimental stage.

However this isn't a big problem because we typically solve the problem with
the current Boost.Range like this:

#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/irange.hpp>
#include <boost/range/algorithm_ext/push_back.hpp>
#include <vector>

int main(int argc, char *argv[])
{
std::vector<int> vec;
boost::push_back(vec, boost::irange(0, 10) | boost::adaptors::reversed);
return 0;
}

The adaptor is more typically applied to the right-hand side of the
expression, and the population of a target container is normally better
achieved by using one the algorithm_ext functions. In this case I am
demonstrating the use of push_back.

This is better arrangement over the example code because the size does not
have to be ascertained twice (once in the constructor of vec, and again in
the actual source expression).

The other alternative arrangements that are equally safe to the new
push_back use an back_insert_iterator which is less efficient.

Hence the new algorithms for transferring ranges to containers are safer,
cleaner and more efficient than the alternative designs.

> Best regards,
>
> Denis
>
>
Regards,
Neil Groves



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