如何对unique_ptr向量进行排序

How can I sort a vector of unique_ptr?

本文关键字:向量 排序 ptr unique      更新时间:2023-10-16

我声明了一个向量,如下所示:vector<unique_ptr<Worker>> Workers . Worker 是具有私有字段name的基类,它有两个派生类:BuilderDriver

我添加到 BuilderDriverWorkers矢量对象,然后我想通过使用这样的#include <algorithm> name对矢量进行排序:

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

但是VS编译器说:

错误 1 错误 C2664: 'bool (const Worker &,const Worker &)' :

无法将参数 2 从 'std::unique_ptr>' 转换为 'const Worker &' c:\program files (x86)\Microsoft Visual Studio 12.0\vc\include\algorithm 3071 1 应用

如何修复此错误?


感谢@NathanOliver、@Rabbid76和这个问题,我将cmp_by_name编辑成以下形式:

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

我像这样调用排序函数:

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

std::sort使用的比较函数需要采用以下形式:

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

这里的类型Type1Type2必须能够取消引用迭代器,然后隐式转换为它们。

在您的情况下,取消引用Workers.begin()会给您一个unique_ptr<Worker>而不是Worker。您需要更改比较函数才能进行const unique_ptr<Worker>&

在这种情况下,它最终看起来像:

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

std::vector<std::unique_ptr<Worker>>的数据类型是 std::unique_ptr<Worker> ,所以你的比较函数必须看起来像这样:

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

比较函数期望参数,以便std::vector的对象可以转换为它们。

从 C++11 开始,您还可以使用 lambda 表达式而不是定义比较函数:

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

注意:为了清楚起见,此示例直接使用Worker对象,但它也适用于派生的BuilderDriver对象。

Ideone上的代码