显式复制构造函数和std :: sort

Ger*_*ncy 12 c++ sorting explicit std

当对具有显式复制ctor的对象的容器进行排序时,我得到编译器错误(来自g ++ 4.8.2和clang ++ 3.4,两者都在-std = c ++ 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;
}
Run Code Online (Sandbox Code Playgroud)

这失败了

error: 
  no matching constructor for initialization of '_ValueType' (aka 'A')
Run Code Online (Sandbox Code Playgroud)

在clang ++和

error: no matching function for call to ‘A::A(std::remove_reference<A&>::type)
Run Code Online (Sandbox Code Playgroud)

用g ++.如果复制构造函数不是显式的,代码编译并正常工作(但我想强制只对我的对象的引用可以用作参数并返回值).删除调用后代码也会编译std::sort(所以is_less(objects[1], objects[2])不是问题).因此我的问题是std :: sort在调用比较函数时会做什么,这会使编译此代码失败以及如何解决它.

经过大量的研究,接近我的问题的唯一问题是在复制初始化中,是复制构造函数的显式还是隐式调用?链接到gcc中的错误.然而,clang表现出相同的行为,所以我真的很想了解发生了什么.

int*_*jay 12

std::sort要求元素类型为MoveConstructible.

MoveConstructible表达式T u = rv;必须有效的状态要求.但是,此表达式执行复制初始化并要求存在非显式复制或移动构造函数.

在这种情况下,复制构造函数是显式的,并且声明它意味着没有隐式声明的移动构造函数.因此,表达式无效,而类A不是MoveConstructible.

  • 使表达式无效的原因不仅仅是复制构造函数是显式的,而且作为仅仅具有复制构造函数的副作用,移动构造函数被禁用.使用移动构造函数和移动赋值运算符,它确实有效,即使复制构造函数仍然是显式的. (7认同)