2014-08-27 22 views
12

Khi sắp xếp một container đối tượng có một bản sao rõ ràng ctor tôi nhận được lỗi trình biên dịch (từ g ++ 4.8.2 và clang ++ 3.4, cả trong -std = C++ 11 chế độ) mà tôi don không hiểu. Tôi đã tạo một ví dụ đơn giản để chứng minh vấn đềconstructor sao chép rõ ràng và std :: loại

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

này không thành công với

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

trong vang ++ và với

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

trong g ++. Mã biên dịch và hoạt động tốt nếu hàm tạo bản sao không rõ ràng (nhưng tôi muốn thực thi rằng chỉ tham chiếu đến đối tượng của tôi mới có thể được sử dụng làm tham số và giá trị trả về). Mã này cũng biên dịch sau khi xóa cuộc gọi đến std::sort (vì vậy is_less(objects[1], objects[2]) không phải là vấn đề). Do đó câu hỏi của tôi là những gì std :: sort thực hiện khi gọi hàm so sánh làm cho việc biên dịch mã này thất bại và cách khắc phục nó.

Sau nhiều nghiên cứu, câu hỏi duy nhất gần với vấn đề của tôi là In copy-initialization, is the call to the copy constructor explicit or implicit? liên kết tới lỗi trong gcc. Tuy nhiên, kêu vang cho thấy hành vi tương tự, vì vậy tôi thực sự muốn hiểu những gì đang xảy ra.

+6

Chỉ những người điên làm cho các nhà xây dựng sao chép 'rõ ràng', các loại như vậy không phải là CopyConstructible –

Trả lời

12

std::sort yêu cầu loại phần tử là MoveConstructible.

Yêu cầu đối với MoveConstructible nêu rõ rằng biểu thức T u = rv; phải hợp lệ. Tuy nhiên, biểu thức này thực hiện khởi tạo bản sao và yêu cầu có một bản sao không rõ ràng hoặc di chuyển constructor.

Trong trường hợp này, hàm tạo bản sao là rõ ràng và khai báo nó có nghĩa là không có hàm tạo di chuyển được khai báo ngầm. Do đó, biểu thức không hợp lệ và lớp A không phải là MoveConstructible.

+7

Điều gì làm cho biểu thức không hợp lệ không chỉ là trình tạo bản sao rõ ràng, mà còn là tác dụng phụ của việc chỉ có một hàm tạo bản sao. vị trí, hàm khởi tạo di chuyển bị vô hiệu hóa. Với một hàm khởi tạo và di chuyển toán tử gán, nó hoạt động, ngay cả khi hàm tạo bản sao vẫn còn rõ ràng. – hvd

Các vấn đề liên quan