Подтвердить что ты не робот

Явный конструктор копирования и 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 показывает такое же поведение, поэтому мне очень хотелось бы понять, что происходит.

4b9b3361

Ответ 1

std::sort требует, чтобы тип элемента был MoveConstructible.

В требованиях для MoveConstructible указано, что выражение T u = rv; должно быть действительным. Однако это выражение выполняет инициализацию копирования и требует, чтобы существовал неявный механизм копирования или перемещения.

В этом случае конструктор копирования является явным, и объявление означает, что не существует неявно объявленного конструктора перемещения. Следовательно, выражение недопустимо, а класс A не MoveConstructible.