How can I sort a vector of unique_ptr?

iterate over vector of unique_ptr
std::sort
fill vector of unique_ptr
unique_ptr implementation
array of unique_ptr
unordered_set of unique_ptr
c++ remove unique_ptr from vector
c vector of unique pointers

I declared a vector as follows: vector<unique_ptr<Worker>> Workers. Worker is a base class with a private field name and it has two derived classes: Builder and Driver.

I add to the Workers vector objects of Builder and Driver and then I want to sort the vector by name using #include <algorithm> like this:

sort(Workers.begin(), Workers.end(), cmp_by_name);

bool cmp_by_name(const Worker &a, const Worker &b)
{
    return a.getName() < b.getName();
}

But the VS compiler says:

Error 1 error C2664: 'bool (const Worker &,const Worker &)' : cannot convert argument 2 from 'std::unique_ptr>' to 'const Worker &' c:\program files (x86)\microsoft visual studio 12.0\vc\include\algorithm 3071 1 App

How can I fix this error?


Thanks to @NathanOliver, @Rabbid76 and this question, I edited my cmp_by_name into this form:

struct cmp_by_name
{
    inline bool operator()(const unique_ptr<Worker>& a, const unique_ptr<Worker>& b)
    {
        return a->getName() < b->getName();
    }
};

And I call the sort function like this:

sort(Workers.begin(), Workers.end(), cmp_by_name());

The comparison function which std::sort uses needs to be in the form of:

bool cmp(const Type1 &a, const Type2 &b);

Here the types Type1 and Type2 must be such that the iterator can be dereferenced and then implicitly converted to both of them.

In your case dereferencing Workers.begin() gives you a unique_ptr<Worker> not a Worker. You will need to change your comparison function to take a const unique_ptr<Worker>&.

In this case it would wind up looking like:

bool cmp_by_name(const std::unique_ptr<Worker>& a, const std::unique_ptr<Worker>& b)
{
    return a->getName() < b->getName();
}

C++11: using unique_ptr with standard library containers, To put it simply, unique_ptr should be the default smart pointer used by new It shows how much more expensive it is to sort a vector of large  Well I know Scott Meyers talked about it in Effective STL, but not sure why vector of unique_ptr will work. I know that unique_ptr is implemented by c++0x move semantics, so we are back to the I know that unique_ptr is implemented by c++0x move semantics, so we are back to the

The datatype of your std::vector<std::unique_ptr<Worker>> is std::unique_ptr<Worker>, so your comparison function has to look like this:

bool cmp_by_name(const std::unique_ptr<Worker> &a, const std::unique_ptr<Worker> &b)
{
    return a->getName() < b->getName();
}

The comparison function expects to arguments so that an object of the std::vector can convert to them.

why is it possible to sort a vector of unique_ptrs?, typedef unique_ptr datum_t; vector x; x.push_back(datum_t(new With auto_ptr and C++03 sort() semantics, it's entirely possible that an  As it turns out, sorting algorithms like quick-sort and heap-sort can in fact work in-place without difficulty. quick-sort's partition routine uses std::swap internally, which counts as a move operation for both objects involved. When selecting a pivot, one trick is to swap it with the first element in the range, this way it will never be moved until partitioning is finished.

Since C++11, you can also use a lambda expression instead of defining a comparison function:

int main()
{
    using workers_t = std::unique_ptr<Worker>;
    std::vector<workers_t> Workers;
    Workers.emplace_back(std::make_unique<Worker>(Worker("Paul")));
    Workers.emplace_back(std::make_unique<Worker>(Worker("Anna")));
    Workers.emplace_back(std::make_unique<Worker>(Worker("John")));

    std::sort(std::begin(Workers), std::end(Workers), [](const workers_t& a, const workers_t& b) {
        return a->getName() < b->getName();
    });

    for (auto const &worker : Workers)
        std::cout << worker->getName() << std::endl;

    return 0;
}

Note: This example directly uses Worker objects for the sake of clarity, but it should work for your derived Builder and Driver objects as well.

Code on Ideone

Vector of Objects vs Vector of Pointers And , From an engineering perspective, sorting functions are designed to sort things. Abusing it to shuffle an array is kind of just asking for trouble, because you never​  Even though unique_ptr can't be copied, it can be moved. It shows how much more expensive it is to sort a vector of large objects that are stored by value, than it is when they're stored by pointer . First, let's create a synthetic "large" object th

A basic introduction to unique_ptr, Transferring a std::unique_ptr to another std::unique_ptr is an easy thing to do: And we would use the base class polymorphically by holding it with some sort of handle (pointer or Here is how it works with std::vector :. If I have two vector containing std::unique_ptr<>, is there a way to add vector b to the end of vector a, thereby deleting vector b? For example:

How to Transfer unique_ptrs From a Set to Another Set, It should either return an std::size_t (usually assumed), std::vector<std::​unique_ptr<T>>::size_type (very lengthy), or even better and shorter with C++14 (​if your  Since there can be only one, one should also be able to pass a temporary directly to the vector: vec.push_back(std::unique_ptr<int>(new int(1)));. unique_ptr can also use a custom deleter (which does nothing), but then one must take into account that the address of the local variable becomes invalid at the end of the scope.

A pointer vector sorted by its member function, If your vector should hold std::unique_ptr<Fruit> instead of raw pointers (to prevent memory leaks). vector sort(vec_byuniqptr.begin(), vec_byuniqptr.end(), This requires a class containing the GetVectorOfResources to be though of as a Collection. And it makes sense as I think about it. Heres another thing then: What if one class returns a result of some processing as vector<unique_ptr<HeavyResource>> (it passes the ownership of the results to the caller), and it is supposed to be used for some subsequent processing: vector<unique_ptr

Comments
  • Signature of the predicate is wrong.
  • You should move the part with your solution into a new answer. This way, your post would better fit Stack Overflow's Q&A format and people could provide upvotes for you solution.
  • Can you tell me how should I call function sort(Workers.begin(), Workers.end(), cmp_by_name); in that case?
  • @DaArtagnan I am not sure what you mean. If you chage cmp_by_name to the way I have it in the answer then it should work.