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();
}
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With