如何对 unique_ptr 的向量进行排序?
How can I sort a vector of unique_ptr?
我声明了一个向量如下:vector<unique_ptr<Worker>> Workers
。 Worker
是一个带有私有字段 name
的基础 class,它有两个派生的 classes:Builder
和 Driver
.
我添加到 Builder
和 Driver
的 Workers
矢量对象,然后我想使用 #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);
这里的类型 Type1
和 Type2
必须使迭代器可以被取消引用,然后隐式转换为它们。
在你的情况下取消引用 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
对象,但它也应该适用于派生的 Builder
和 Driver
对象。
我声明了一个向量如下:vector<unique_ptr<Worker>> Workers
。 Worker
是一个带有私有字段 name
的基础 class,它有两个派生的 classes:Builder
和 Driver
.
我添加到 Builder
和 Driver
的 Workers
矢量对象,然后我想使用 #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);
这里的类型 Type1
和 Type2
必须使迭代器可以被取消引用,然后隐式转换为它们。
在你的情况下取消引用 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
对象,但它也应该适用于派生的 Builder
和 Driver
对象。