我的问题是为什么我可以用开头/结尾排序一个唯一指针的向量,但不能用cbegin / cend排序
编译:
std::sort(teachers.begin(), teachers.end(), compare_by_uniqptr);
但由于某种原因,这给了我一个C2280试图引用已删除的功能。
std::sort(teachers.cbegin(), teachers.cend(), compare_by_uniqptr);
以下是一些背景信息。 '教师'是教师对象的唯一指针的向量。
class Teacher : public Person {
private:
std::vector<std::unique_ptr<Student>> students;
public:
Teacher(std::string name) : Person(name) {}
void insert(std::string name);
int num_students() { return students.size(); }
};
std::vector<std::unique_ptr<Teacher>> teachers;
bool compare_by_uniqptr(const std::unique_ptr<Teacher>& a,
const std::unique_ptr<Teacher>& b)
{
return a.get()->num_students() > b.get()->num_students();
}
我按照每个学生按降序排列的学生数量对它们进行排序。开始/结束编译但cbegin / cend没有编译。为什么呢?
答案 0 :(得分:2)
因为std::sort
通过移动来对范围内的元素进行排序。这意味着元素将通过迭代器进行修改;它不适用于const
的迭代器。
答案 1 :(得分:2)
无法复制唯一指针(否则它们将失去其唯一性)。出于这个原因,当它们被排序时,它们将需要移动(或交换)。这些操作需要更改唯一指针的 internals 。当然,你不能通过const引用来改变对象的内部。
答案 2 :(得分:1)
为什么cbegin()
和cend()
不起作用? documentation中所述的std::sort()
具有以下类型要求:
重点是我的。所以-RandomIt必须满足ValueSwappable和RandomAccessIterator的要求。
- 取消引用的RandomIt类型必须符合MoveAssignable和MoveConstructible 的要求。
- 比较必须符合比较的要求。
std::vector::const_iterator
不满足这些要求。所以,即使你有std::vector<int>
并尝试使用它们也无效。如果您使用begin()
在end()
/ std::unique_ptr
上询问原因,那么您也可以在documentation中看到它:
std :: swap(std :: unique_ptr)(C ++ 11)专门研究std :: swap算法 (功能模板)
因此std::unique_ptr
值满足ValueSwappable概念。
答案 3 :(得分:0)
这是一个解决方案。兼容到c ++ 11:
#include <vector>
#include <string>
#include <memory>
#include <algorithm>
struct Person {
Person(std::string name);
};
struct Student : Person {
};
class Teacher : public Person {
private:
std::vector<std::unique_ptr<Student>> students;
public:
Teacher(std::string name) : Person(name) {}
void insert(std::string name);
int num_students() const { return students.size(); }
};
std::vector<std::unique_ptr<Teacher>> teachers;
struct by_num_students
{
bool operator()(Teacher const& l, Teacher const& r) const
{
return l.num_students() < r.num_students();
}
};
template<class Comp>
struct by_pointee_impl
{
template<class L, class R>
bool operator()(L&& l, R&& r) const
{
return comp(*l, *r);
}
Comp comp;
};
template<class Comp>
auto by_pointee(Comp comp) -> by_pointee_impl<Comp>
{
return by_pointee_impl<Comp>{comp};
};
int main()
{
std::sort(begin(teachers), end(teachers), by_pointee(by_num_students()));
}