2011-12-07 32 views
11

Được cung cấp std::vector<std::unique_ptr<SomeType> >, việc sử dụng remove_if có hợp pháp không? Nói cách khác, với mã này:Bạn có thể sử dụng `std :: remove_if` trên vùng chứa` std :: unique_ptr` không?

std::vector<std::unique_ptr<SomeType> > v; 
// fill v, all entries point to a valid instance of SomeType... 
v.erase(std::remove_if(v.begin(), v.end(), someCondition), v.end()); 

, tôi đảm bảo sau khi erase rằng tất cả các con trỏ vẫn ở v là hợp lệ. Tôi biết rằng việc triển khai trực quan std::remove_if và được cung cấp tất cả các triển khai mà tôi đã xem, chúng sẽ là. Tôi muốn biết nếu có bất cứ điều gì trong tiêu chuẩn mà đảm bảo nó; tức là std::remove_if không được phép sao chép bất kỳ mục nhập hợp lệ nào mà không sao chép bản sao vào vị trí cuối cùng .

(Tôi, tất nhiên, giả rằng tình trạng này không sao chép Nếu điều kiện có một chữ ký như:.

struct Condition 
{ 
    bool operator()(std::unique_ptr<SomeType> ptr) const; 
}; 

, thì tất nhiên, tất cả các con trỏ sẽ không hợp lệ sau remove_if.)

+7

James Kanze đặt câu hỏi - một hiện tượng rất hiếm! – Nawaz

+3

'unique_ptr' không phải là bản sao có thể xây dựng được, vì vậy nếu bạn đã sử dụng vị ngữ đó, mã của bạn sẽ không biên dịch. – interjay

+1

Tại sao không? 'std :: unique' không thể sao chép được nhưng có thể di chuyển được. Nó có thể được chuyển đến cuối container. –

Trả lời

2

25.3.8 trong N3290 nói về loại bỏ chức năng:

Yêu cầu: Các loại * đầu tiên phải đáp ứng các yêu cầu MoveAssignable (Bảng 22).

Lưu ý: mỗi phần tử trong khoảng [ret, họ), nơi ret là trở giá trị, có một trạng thái fi ed hợp lệ nhưng unspeci, bởi vì các thuật toán có thể loại bỏ các yếu tố bằng cách trao đổi có hoặc di chuyển từ các yếu tố đã là ban đầu trong phạm vi đó.

Điều này có nghĩa là tùy thuộc vào toán tử vị ngữ của bạn. Vì vị từ của bạn không tạo bản sao nên các phần tử sẽ không được sao chép.

+0

§25.3.8/1 là một ràng buộc đối với loại nhắm mục tiêu, chứ không phải trên việc triển khai thực hiện 'xóa bỏ' . §25.3.8/6 là những gì tôi đang tìm kiếm. Quá không phải là một lưu ý và không phải là quy tắc. Nhưng nó làm cho ý định rõ ràng. Tôi đã đọc các ghi chú và không chỉ là văn bản quy phạm, trước khi đăng . 1 anyway, và tôi sẽ xem xét nó phản ứng cuối cùng nếu không ai tìm thấy bất cứ điều gì rõ ràng hơn. –

+0

Tôi có n3242. §25.3.8/6 được thêm vào sau đó? My/6 thảo luận về 'remove_copy [_if]'. – kennytm

+2

Tôi tin rằng lưu ý là không chính xác. Điều tốt nó không phải là quy tắc. ;-) Thuật toán không được phép hoán đổi các phần tử bởi vì các phần tử không bắt buộc phải Swappable. Thuật toán chỉ có thể sử dụng nhiệm vụ di chuyển. –

5

Cũng giống như erase()resize(), remove_if() sẽ di chuyển yếu tố (có thể thông qua trao đổi), vì vậy các yếu tố chứa không cần phải được copyable. Không có gì đặc biệt về unique_ptr, nó chỉ là một loại di chuyển khác.

Khi bạn chỉ ra, biến vị ngữ dĩ nhiên nên lấy các phần tử bằng tham chiếu const. Một lần nữa, cũng giống như đối với bất kỳ loại di chuyển nào.

+0

Điều này được nêu trong tiêu chuẩn ở đâu? Và quan trọng hơn, ở đâu là nói rằng 'remove_if' không chuyển sang một số tạm thời, có lẽ sau này để để lại giá trị ở đó bởi vì nó xác định rằng không cần đặt nó ở nơi khác? Các vùng chứa và các hàm thành viên đã được viết lại để phản ánh ngữ nghĩa di chuyển, nhưng tôi không biết bất kỳ thay đổi nào trong ngôn ngữ mô tả 'remove_if' trong lĩnh vực này. –

+1

@JamesKanze: §25.3.8/1? – kennytm

+0

@KennyTM: Hãy đánh bại tôi, cảm ơn! –

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