Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fast way to convert std::list of pointer to std::list of value

I have a std::list<obj*>, where obj is my class:

std::list<obj*> list_of_ptr;
list_of_ptr.push_back(new obj());

I want to convert this list to the equivalent std::list<obj>, after that I no longer need the list_of_ptr.

What is the fastest way to do this work?

like image 776
Nick Avatar asked Dec 11 '25 09:12

Nick


2 Answers

std::transform is your friend:

std::vector<obj> objects;
std::transform(
    list_of_ptr.begin(), list_of_ptr.end(),
    std::back_inserter(objects), 
    [](obj* p) { return *p; });

Or, if C++11 lambda expressions cannot be used, one may use a simple function object to perform the indirection:

struct indirect
{
    template <typename T>
    T& operator()(T* p) { return *p; }
};

std::transform(
    list_of_ptr.begin(), list_of_ptr.end(),
    std::back_inserter(objects), 
    indirect());

Or, using boost::indirect_iterator:

std::vector<obj> objects(
    boost::make_indirect_iterator(list_of_ptr.begin()),
    boost::make_indirect_iterator(list_of_ptr.end()));

These, of course, assume that there are no null pointers in the sequence. It is left as an exercise for the reader to figure out how to correctly manage the lifetimes of the objects pointed to by the pointers in list_of_ptr.

Ideally, one would use a std::vector<obj> from the start, or, if that is not possible, a container of smart pointers. Manually managing the lifetimes of the pointed-to objects, and doing so correctly, is very difficult. C++ has awesome automatic object lifetime management facilities (destructors, smart pointers, containers, stack semantics, RAII), and there is no reason not to use them.

like image 171
James McNellis Avatar answered Dec 13 '25 00:12

James McNellis


Simplicity and code that is easy to understand is also your friend:

for each (obj* pObj in list_of_ptr)
{
    if (pObj != nullptr)
    {
        list_of_objects.push_back(*pObj);
    }
}

And if that doesn't compile for you, this certainly should:

std::list<obj> list_of_objects;

for_each(list_of_ptr.begin(), list_of_ptr.end(), [&list_of_objects] (obj* pObj) {
    if (pObj != nullptr)
        list_of_objects.push_back(*pObj);
});
like image 45
selbie Avatar answered Dec 12 '25 23:12

selbie



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!