Björn Pollex
Björn Pollex

Reputation: 76778

Using boost.assign on collection of shared_ptr

Consider the following snippet:

class Foo {
public:
    Foo( int Value );

    // other stuff
};

std::list< boost::shared_ptr< Foo > > ListOfFoo = list_of( 1 )( 2 )( 3 )( 4 )( 5 );

This does not work out of the box. What is the simplest way to make this work, or is there any method to assign values to ListOfFoo as simple as that?

Upvotes: 3

Views: 1039

Answers (4)

Manuel
Manuel

Reputation: 13099

boost::assign::ptr_list_of lets you construct a Boost pointer container with a very simple syntax. You can extend it through private inheritance so that it lets you create containers of shared_ptr:

template< class T > 
struct shared_ptr_list : boost::assign_detail::generic_ptr_list<T>
{
    typedef boost::assign_detail::generic_ptr_list<T> Base;

    template< class Seq >
    operator Seq() const 
    {
        Seq result;
        for(typename Base::impl_type::iterator it = Base::values_.begin(), e = Base::values_.end(); it != e; ++it)
            result.push_back(typename Seq::value_type(&*it));
        Base::values_.release().release();
        return result;
    }     

    template< class U >
    shared_ptr_list& operator()( const U& u )
    {
        return (shared_ptr_list&)boost::assign_detail
               ::generic_ptr_list<T>::operator()(u);
    }    
};

template< class T, class U >
shared_ptr_list<T> shared_ptr_list_of( const U& t )
{
    return shared_ptr_list<T>()(t);
}

It looks a bit ugly but then it's really convenient to use:

int main()
{
    using boost::shared_ptr;
    std::deque<shared_ptr<Foo> > deq = shared_ptr_list_of<Foo>(1)(2)(3);
}

Upvotes: 3

visitor
visitor

Reputation: 8834

Another way would be to use std::transform on an array of arguments:

const unsigned DataSize = 5;
int data[DataSize] = {1, 2, 3, 4, 5};
std::list<boost::shared_ptr<Foo> > ListOfFoo;
std::transform(data, data + DataSize, std::back_inserter(ListOfFoo), &boost::make_shared<Foo, int>);

Perhaps looks nicer if the list is to be even larger.

Upvotes: 2

Nikola Smiljanić
Nikola Smiljanić

Reputation: 26873

std::list<boost::shared_ptr<Foo> > ListOfFoo = boost::assign::list_of(boost::make_shared<Foo>(1))(boost::make_shared<Foo>(2));

There is no implicit conversion from Foo* to shared_ptr<Foo>.

shared_ptr<Foo> ptr = new Foo(1); // you can't do this
shared_ptr<Foo> ptr(new Foo(1)); // this is ok
shared_ptr<Foo> ptr = make_shared<Foo>(1); // this is also ok

What you want is impossible, you have to explicitly create shared pointers and pass them to list_of.

Upvotes: 1

Yukiko
Yukiko

Reputation: 1123

Your boost::list_of requires objects of type boost::shared_ptr<Foo>. So you could do it as follows:

typedef boost::shared_ptr<Foo> FooPtr;

std::list<boost::shared_ptr<Foo> > fooList = list_of
    (FooPtr(new Foo(1))
    (FooPtr(new Foo(2))
    (FooPtr(new Foo(3));

Upvotes: 1

Related Questions