如何对 unique_ptr 的向量进行排序?

How can I sort a vector of unique_ptr?

我声明了一个向量如下:vector<unique_ptr<Worker>> WorkersWorker 是一个带有私有字段 name 的基础 class,它有两个派生的 classes: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 编译器说:

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

我该如何解决这个错误?


感谢@NathanOliver、@Rabbid76 和 this question,我将我的 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, you can also use a lambda expression 而不是定义比较函数:

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 对象。

Code on Ideone