Explicit copy constructor and std::sort

拥有回忆 提交于 2019-12-06 18:51:50

问题


When sorting a container of objects having an explicit copy ctor I get compiler errors (from g++ 4.8.2 and clang++ 3.4, both in -std=c++11 mode) that I don't understand. I've created a simple example to demonstrate the problem

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

This fails with

error: 
  no matching constructor for initialization of '_ValueType' (aka 'A')

in clang++ and with

error: no matching function for call to ‘A::A(std::remove_reference<A&>::type)

in g++. The code compiles and works fine if the copy constructor is not explicit (but I want to enforce that only references to my objects can be used as parameters and return values). The code also compiles after removing the call to std::sort (so is_less(objects[1], objects[2]) is not a problem). Hence my question is what std::sort does when calling the comparing function that makes compiling this code fail and how to fix it.

After a lot of research, the only question that came close to my problem is In copy-initialization, is the call to the copy constructor explicit or implicit? which links to a bug in gcc. However, clang shows the same behavior, so I'd really like to understand what's going on.


回答1:


std::sort requires that the element type be MoveConstructible.

The requirements for MoveConstructible state that the expression T u = rv; must be valid. However, this expression performs copy initialization and requires that there is a non-explicit copy or move constructor.

In this case, the copy constructor is explicit, and declaring it means that there is no implicitly-declared move constructor. Therefore, the expression is invalid, and the class A is not MoveConstructible.



来源:https://stackoverflow.com/questions/25529772/explicit-copy-constructor-and-stdsort

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!