2012-09-28 6 views
8

Tôi có một số std::vector<Foo> trong đó Foo là một lớp có chứa Foo(Foo&&) noexcept.std :: vector :: erase() không muốn di chuyển

Thêm đối tượng vào vùng chứa hoạt động hoàn hảo, tuy nhiên việc xóa chúng bằng cách sử dụng std::vector::erase(iterator) thì không, GCC 4.7 cố gắng gọi toán tử gán mà tôi đã xóa. Các thông báo lỗi chính xác là:

lỗi: sử dụng chức năng xóa 'Foobar & Foobar :: operator = (const Foobar &)

Edit: Tất nhiên std::vector gọi toán tử gán, không phải là bản sao constructor (bạn cũng có thể thấy điều đó trong thông báo lỗi). Cố định nó trong phần mô tả, xin lỗi.

Dưới đây là ví dụ mã nguồn theo yêu cầu:

#include <vector> 

class Foo { 
    public: 
     Foo() {} 
     Foo(Foo&& other) noexcept {} 

     Foo(const Foo&) = delete; 
     Foo& operator=(const Foo&) = delete; 
}; 

int main() { 
    std::vector<Foo> v; 

    v.push_back(Foo{}); 
    v.erase(v.begin()); 
} 
+1

Bạn có mã demo không? – kennytm

+0

Nếu không có mã, thật khó để xem vấn đề là gì – sehe

+0

Mã nguồn được thêm vào. :-) – stschindler

Trả lời

11

Vấn đề là bạn không cung cấp một toán tử gán di chuyển. Đây là một phần của vectơ Yêu cầu di chuyển đối với một số chức năng.

+0

Oh. Hehe. Tôi vừa nhập mẫu của riêng mình và tự động thêm toán tử gán di chuyển. Giải thích lý do tại sao nó làm việc cho tôi sau đó :) +1 – sehe

+0

+1 cũng phát hiện! – Walter

+1

Lỗi trình biên dịch cho phép tất cả đi - không có 'toán tử =' phù hợp. – Puppy

2

tôi không thể tái tạo nó. Biến ra thói quen tốt đi một chặng đường dài: Tôi đã xác định được toán tử asignment.

Live trên GCC 4.7.2: http://liveworkspace.org/code/36c600c285f2c91649fd4f73784c2c00

#include <iostream> 
#include <vector> 

struct Foo 
{ 
    Foo() {} 

    Foo(Foo const&) = delete; 
    Foo(Foo&&) throw() { } 

    Foo& operator=(Foo const&) = delete; 
    Foo& operator=(Foo&&) throw() { return *this; } 
}; 

int main(int argc, char* args[]) 
{ 
    std::vector<Foo> v; 
    v.emplace_back(); 
    v.emplace_back(); 
    v.emplace_back(); 
    v.emplace_back(); 

    auto it = v.begin(); 
    it++; 
    v.erase(it); 
} 
+0

Thực ra là một ý tưởng rất hay, tuy nhiên 'erase()' không thích trình dịch chuyển di chuyển, nó nói không có hàm gọi hàm nào phù hợp với 'std :: move_iterator <...>'. – stschindler

+1

Tôi vừa nhận thấy và cập nhật mã. Nó chỉ ra rằng trong 'phát minh ra' mẫu nhân bản, tôi tự động xác định toán tử gán di chuyển, như @DeadMG gợi ý. Thói quen ... – sehe

+0

Hehe, thú vị. Cảm ơn rất nhiều, cung cấp cho nhà điều hành chuyển nhượng cũng có ý nghĩa hoàn hảo. – stschindler

1

câu trả lời DeadMG là tuyệt vời, tuy nhiên tôi muốn quảng bá một cách khác để viết toán tử gán:

struct Foo { 
    Foo() {} 

    Foo(Foo const&) = delete; 
    Foo(Foo&&) throw() { } 

    Foo& operator=(Foo) throw() { return *this; } 
}; 

Kể từ khi bạn yêu cầu tạm thời tươi vào lúc bắt đầu của phương pháp này, trình biên dịch sẽ chọn một trong hai sao chép hoặc di chuyển hàm tạo để tạo tạm thời này và bạn không phải viết cả toán tử gán bản sao VÀ toán tử gán di chuyển :)

+0

Anh ấy không sao, vì lớp học của anh ấy không thể đọc được. – Puppy

+0

@DeadMG: Tôi sẽ tránh nhập vào các chi tiết của những gì được tự động mặc định và những gì được tự động xóa ... nó quá kỳ quặc. –