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

时间:2016-01-20 17:05:06

标签: c++ sorting c++11 vector unique-ptr

我声明了一个向量:vector<unique_ptr<Worker>> WorkersWorker是一个包含私有字段name的基类,它有两个派生类:BuilderDriver

我添加到WorkersBuilder的{​​{1}}向量对象,然后我想使用Drivername对向量进行排序,如下所示:< / p>

#include <algorithm>

但VS编译器说:

  

错误1错误C2664:'bool(const Worker&amp;,const Worker&amp;)':无法从'std :: unique_ptr&gt;'转换参数2到'const Worker&amp;' c:\ program files(x86)\ microsoft visual studio 12.0 \ vc \ include \ algorithm 3071 1 App

如何解决此错误?

感谢@NathanOliver,@ Rabbid76和this question,我将sort(Workers.begin(), Workers.end(), cmp_by_name); bool cmp_by_name(const Worker &a, const Worker &b) { return a.getName() < b.getName(); } 编辑为此表单:

cmp_by_name

我将sort函数称为:

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

3 个答案:

答案 0 :(得分:13)

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

答案 1 :(得分:5)

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的对象可以转换为它们。

答案 2 :(得分:0)

C++11起,您也可以使用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