当对具有显式复制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;
}
失败
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在调用比较函数时会做什么,这使得编译此代码失败以及如何修复它。
经过大量研究后,接近我问题的唯一问题是In copy-initialization, is the call to the copy constructor explicit or implicit?链接到gcc中的错误。但是,clang表现出相同的行为,所以我真的很想了解发生了什么。
答案 0 :(得分:12)
std::sort
要求元素类型为MoveConstructible
。
MoveConstructible
的要求声明表达式T u = rv;
必须有效。但是,此表达式执行复制初始化并要求存在非显式复制或移动构造函数。
在这种情况下,复制构造函数是显式的,并且声明它意味着没有隐式声明的移动构造函数。因此,表达式无效,而类A
不是MoveConstructible
。