Boost logo

Boost Users :

Subject: Re: [Boost-users] [range] What's the best way to initialize a new container from a range?
From: Alastair Rankine (arsptr_at_[hidden])
Date: 2011-08-30 07:19:21


On 2011-08-26 12:30:42 +0000, Martin B. said:

> Hi!
>
> Say I have a range R and I want to construct a new container from the
> range R. Will I always have to repeat the expression yielding the range,
> or is there a shorter way?

This is an interesting topic.

There is *almost* a way to do what you want, using boost assign
list_of, as per the example below. Note that I am assuming that you
want to do this efficiently, hence use the slightly less convenient
(because of the size parameter) cref_list_of function.

There are two main problems with this approach.

1. The initial element of the range has to be explictly provided to
cref_list_of. This is the 0 element in the examples below.

2. The range() function for cref_list_of completely fails when using a
boost::irange. With the exception of the initial value, the container
is filled with the final value of the irange (5 in this example). This
looks like a bug to me…

It would be really good to get boost assign enhanced to remove these
limitations. In fact I wonder if it would be particularly hard to
implement an assign::range_of function which uses the same underlying
mechanism (ie an object which is convertible to the requisite container
type).

#define BOOST_TEST_MODULE assignrange
#include <boost/test/unit_test.hpp>

#include <boost/array.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/range/irange.hpp>

BOOST_AUTO_TEST_CASE(assignrange)
{
    const boost::array<int, 5> input = {{ 1, 2, 3, 4, 5 }};

    const std::vector<int> ivec =
boost::assign::cref_list_of<6>(0).range(input);

    const boost::array<int, 6> expected = {{ 0, 1, 2, 3, 4, 5 }};

    // Test passes
    BOOST_CHECK_EQUAL_COLLECTIONS(ivec.begin(), ivec.end(),
expected.begin(), expected.end());
}

BOOST_AUTO_TEST_CASE(assignirange)
{
    const std::vector<int> ivec =
boost::assign::cref_list_of<6>(0).range(boost::irange(1,6));

    const boost::array<int, 6> expected = {{ 0, 1, 2, 3, 4, 5 }};

    // Test fails!
    BOOST_CHECK_EQUAL_COLLECTIONS(ivec.begin(), ivec.end(),
expected.begin(), expected.end());
}


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