Явный конструктор копирования и std:: sort
При сортировке контейнера объектов, имеющих явную копию ctor, я получаю ошибки компилятора (из g++ 4.8.2 и clang++ 3.4, как в режиме -std = С++ 11), которые я не понимаю. Я создал простой пример, чтобы продемонстрировать проблему.
class A {
public:
explicit A(int i): m_i(i) {};
explicit A(const A& other): m_i(other.m_i) {};
int i() const {return m_i;};
private:
int m_i;
};
bool is_less(const A& a, const A& b) {
return a.i() < b.i();
}
int main(int, char*[]) {
std::vector<A> objects;
objects.push_back(A(3));
objects.push_back(A(5));
objects.push_back(A(-1));
std::cout << is_less(objects[1], objects[2]);
std::sort(objects.begin(), objects.end(), is_less);
for (auto& a: objects) {
std::cout << a.i() << " ";
}
std::cout << std::endl;
}
Это не работает с
error:
no matching constructor for initialization of '_ValueType' (aka 'A')
в clang++ и
error: no matching function for call to ‘A::A(std::remove_reference<A&>::type)
в g++. Код компилируется и отлично работает, если конструктор копирования не является явным (но я хочу, чтобы в качестве параметров и возвращаемых значений можно было использовать только ссылки на мои объекты). Код также компилируется после удаления вызова std::sort
(поэтому is_less(objects[1], objects[2])
не является проблемой). Поэтому мой вопрос заключается в том, что std:: sort делает при вызове функции сравнения, которая заставляет компиляцию этого кода сбой и как его исправить.
После большого количества исследований единственный вопрос, который приблизился к моей проблеме, - В процессе инициализации копии, является ли вызов конструктора копии явным или неявным?, который ссылки на ошибку в gcc. Тем не менее, clang показывает такое же поведение, поэтому мне очень хотелось бы понять, что происходит.
Ответы
Ответ 1
std::sort
требует, чтобы тип элемента был MoveConstructible
.
В требованиях для MoveConstructible
указано, что выражение T u = rv;
должно быть действительным. Однако это выражение выполняет инициализацию копирования и требует, чтобы существовал неявный механизм копирования или перемещения.
В этом случае конструктор копирования является явным, и объявление означает, что не существует неявно объявленного конструктора перемещения. Следовательно, выражение недопустимо, а класс A
не MoveConstructible
.