Boost logo

Boost Users :

Subject: Re: [Boost-users] Ranges to Collections
From: ÇÇ־ǿ (qiaozhiqiang_at_[hidden])
Date: 2011-06-06 22:31:29


Maybe you want make_vector() , make_list().

#include <vector>
#include <list>
#include <boost/range/algorithm.hpp>
#include <boost/range/algorithm_ext/push_back.hpp>

#include <boost/range/adaptor/reversed.hpp> // for test

template<class T, class SinglePassRange>
T make_container(const SinglePassRange& from)
{
        T c;
        boost::push_back(c, from);
        return move(c);
}

template<class SinglePassRange>
std::vector<typename SinglePassRange::value_type> make_vector(const SinglePassRange& from)
{
        return make_container<std::vector<typename SinglePassRange::value_type>>(from);
}

template<class SinglePassRange>
std::list<typename SinglePassRange::value_type> make_list(const SinglePassRange& from)
{
        return make_container<std::list<typename SinglePassRange::value_type>>(from);
}

int main(int argc, _TCHAR* argv[])
{
        std::vector<char> vector1;
        vector1.push_back(1);
        vector1.push_back(2);
        vector1.push_back(3);

        std::list<char> list1;
        list1.push_back(1);
        list1.push_back(2);
        list1.push_back(3);
        
        auto vector2 = make_container<std::vector<char>>(vector1 | boost::adaptors::reversed);
    auto vector3 = make_vector(vector1 | boost::adaptors::reversed);
    auto vector4 = make_vector(vector1);

        auto list2 = make_container<std::list<char>>(list1 | boost::adaptors::reversed);
    auto list3 = make_list(list1 | boost::adaptors::reversed);
        auto list4 = make_list(list1);

        return 0;
}

> ------------------------------
>
> Message: 2
> Date: Mon, 06 Jun 2011 11:00:29 -0500
> From: "John M. Dlugosz" <mpbecey7gu_at_[hidden]>
> To: boost-users_at_[hidden]
> Subject: [Boost-users] Ranges to Collections
> Message-ID: <15775-1307376032-823667_at_[hidden]>
> Content-Type: text/plain; charset=UTF-8; format=flowed
>
> I like "ranges". When I first read the introduction to the ideas that would
> become STL, I
> did not like the use of begin/end iterators. Primarily, there is a possibility
> of getting
> them mixed up and the proposed library was explicitly not robust in the face
> of being
> passed bad parameters, such as not belonging to the same collection or not
> having the end
> after the begin. This was in direct contrast to the code I was promoting, which
> stressed
> API design that prevented errors from being possible, and strongly checking
> for everything
> else. The fact that they are not "functional" was harder to grasp exactly at
> the time,
> but it bothered me "in my gut".
>
> When I read about the Boost Range library and the C++0x adoption of the range
> concept, I
> felt this to be a long sought improvement and would dramatically improve my
> use of STL.
>
> Suffice to say, I'm a fan of Ranges. In new work, and in refactoring and
> improving code,
> I expect ranges to be one of the pillars of improvement. I'm sad to see that
> the draft
> standard dropped most of the range stuff (presumably it needs Concepts) but
> left in the
> intrinsic for-each loop. Anyway, the concrete compiler I have to work with,
> Visual Studio
> 2010, doesn't include it. So Boost.Range to the rescue! Except... the
> standard
> containers like vector don't have constructors that take ranges.
>
> Consider something like:
> vector<string> retval (rangefunc | rangefilter);
>
> It really gets in the way to introduce a temporary variable of "some range type",
> but I
> see that the 'auto' feature comes to the rescue. I'm not used to having that
> available,
> so perhaps I'm over reacting.
>
> But, is there a way to bridge the gap?
>
> I take it patching the STL headers to add the missing constructors is frowned
> upon. But
> some syntactic sugar might get pretty close to that. First of all, what are
> people doing
> now? Maybe this has all be gone over before?
>
> I can see creating a derived class from each STL container. The sole purpose
> of that
> class is to have the range constructor, and then the resulting instance is used
> as the
> base class, passed somewhere or copied. So you might write, for the previous
> example:
> range_vector retval (rangefunc | rangefilter);
>
> and other code won't care about your derived class since it only existed
> district from the
> base class in order to add a constructor. In fact, a template might
> systematically do
> this to any class that has a constructor that takes two iterators:
> rangeit<vector<string>> retval (rangefunc | rangefilter);
>
> This is less than desirable in cases where you were not going to state the type.
> Say, a
> return statement or parameter, where you would ideally have an implicit
> conversion from a
> range to the collection:
> return (rangefunc | rangefilter); // give a "range" where collection is
> expected
>
> Could a helper template be written that has a simple name and doesn't need to
> be told the
> types involved?
> return range_to_collection (rangefunc | rangefilter);
>
> Perhaps this produces a temporary object that supports a templatized conversion
> operator,
> so it can continue when that is told the type desired. I can see a few
> approaches,
> depending on what the compiler would swallow. But, has anyone already done
> this?
>
> ?John
>
>
>


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