Использование boost.assign для коллекции shared_ptr - PullRequest
3 голосов
/ 15 февраля 2010

Рассмотрим следующий фрагмент:

class Foo {
public:
    Foo( int Value );

    // other stuff
};

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

Это не работает из коробки. Какой самый простой способ заставить это работать, или есть какой-нибудь способ присвоить значения ListOfFoo так просто?

Ответы [ 4 ]

3 голосов
/ 15 февраля 2010

boost::assign::ptr_list_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);
}

Это выглядит немного некрасиво, но тогда действительно удобно использовать:

int main()
{
    using boost::shared_ptr;
    std::deque<shared_ptr<Foo> > deq = shared_ptr_list_of<Foo>(1)(2)(3);
}
2 голосов
/ 15 февраля 2010

Другой способ - использовать std::transform для массива аргументов:

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>);

Возможно, выглядит лучше, если список будет еще больше.

1 голос
/ 15 февраля 2010

Для вашего boost :: list_of требуются объекты типа boost::shared_ptr<Foo>. Таким образом, вы можете сделать это следующим образом:

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));
1 голос
/ 15 февраля 2010
std::list<boost::shared_ptr<Foo> > ListOfFoo = boost::assign::list_of(boost::make_shared<Foo>(1))(boost::make_shared<Foo>(2));

Нет неявного преобразования из Foo* в 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

То, что вы хотите, невозможно, вам нужно явно создать общие указатели и передать их list_of.

...