2011-08-01 36 views

Trả lời

3

Bạn sẽ cần phải tìm ra iterator tương ứng với các yếu tố myClass và sau đó vượt qua iterator rằng để mySet.erase(). Trình lặp có thể được tìm thấy bằng cách sử dụng thuật toán std::find_if với một tùy chỉnh Predicate functor hiểu cách dereference unique_ptr và so sánh nó với con trỏ thô myClass.

Bạn không thể sử dụng quá tải size_t set::erase (const key_type& x); vì con trỏ thô (ngay cả khi được bọc trong một unique_ptr tạm thời) sẽ không được tìm thấy trong mySet.

+0

Nếu con trỏ thô được bọc trong một 'unique_ptr tạm <> ', §20.7.1.4/2 đảm bảo rằng' set :: size_type set :: erase (key_type const &); 'overload ** ** sẽ hoạt động. Tuy nhiên, điều đó gần như được đảm bảo để tạo các vấn đề tồn tại đối tượng trừ khi một deleter tùy chỉnh được sử dụng cho tạm thời, vì vậy phương thức 'std :: find_if' có lẽ vẫn tốt hơn. – ildjarn

+0

Tôi không tìm thấy phần liên quan trong tiêu chuẩn năm 1998, tiêu chuẩn sửa đổi năm 2003 hoặc bản thảo C++ 0X mới. Bạn có thể vui lòng hướng dẫn tôi đến tên của tài liệu chính xác mà bạn đang giới thiệu không? –

+0

Tôi đang đề cập đến C++ 0x FDIS (N3290), §20.7.1.4/2, trang 549. – ildjarn

3

Không đẹp như tôi đã thích. Nhưng công việc sau đây thực hiện công việc:

#include <memory> 
#include <set> 
#include <iostream> 

struct do_nothing 
{ 
    void operator()(const void*) const {} 
}; 

struct MyClass 
{ 
    MyClass() {std::cout << "MyClass()\n";} 
    MyClass(const MyClass&) {std::cout << "MyClass(const MyClass&)\n";} 
    ~MyClass() {std::cout << "~MyClass()\n";} 
}; 

int main() 
{ 
    std::set<std::unique_ptr<MyClass>> mySet; 

    MyClass *myClass = new MyClass(); 
    mySet.insert(std::unique_ptr<MyClass>(myClass)); 

    // remove myClass from mySet? 
    std::set<std::unique_ptr<MyClass>>::iterator i = 
     lower_bound(mySet.begin(), mySet.end(), 
        std::unique_ptr<MyClass, do_nothing>(myClass)); 
    if (i != mySet.end() && *i == std::unique_ptr<MyClass, do_nothing>(myClass)) 
     mySet.erase(i); 
} 
+0

Hm, điều này khá xấu, nhưng tôi cho rằng khớp với yêu cầu bất thường: Nếu con trỏ là duy nhất, thì làm sao bạn có thể có một bản sao của nó để tìm kiếm theo giá trị? Tôi nghi ngờ chủ yếu về động cơ của OP. –

+0

Tôi nghĩ rằng tôi có một giải pháp tốt dựa trên đề xuất của bạn. Xem giải pháp đã đăng của tôi. – mazatwork

1

Có vẻ như tôi có thể truy xuất trình lặp bằng cách sử dụng tùy chỉnh Predicate with lower_bound. Kể từ std :: set là một container theo thứ tự, lower_bound nên thực hiện logarithmically.

std::set<std::unique_ptr<MyClass>>::iterator i = 
    std::lower_bound(mySet.begin(), mySet.end(), myClass, MyPredicate<MyClass>()); 

template<class Type> 
struct MyPredicate 
{ 
    bool operator()(const std::unique_ptr<Type>& left, const Type* right) const 
    { 
     return left.get() < right; 
    } 
} 
+0

lower_bound không phải là logarit trong trường hợp này bởi vì trình vòng lặp được trả về bởi tập hợp <>. Begin()/set <>. End() không phải là một RandomAccessIterator. http://en.cppreference.com/w/cpp/algorithm/lower_bound – nilton

0

Tuy không phải là giải pháp tốt nhất nhưng đối với thời điểm hiện tại tôi đi với:

PointerMap<MyFoo>::Type myFoos; 

MyFoo * myFoo = new MyFoo(); 
myFoos.insert(PointerMap<MyFoo>::Item(myFoo)); 

Các tiêu đề là:

#include <map> 
#include <memory> 
#include <utility> 

template<typename T> 
struct PointerMap 
{ 
    typedef std::map<T *, std::unique_ptr<T>> Type; 

    struct Item : std::pair<T *, std::unique_ptr<T>> 
    { 
     Item(T * pointer) 
      : std::pair<T *, std::unique_ptr<T>>(pointer, std::unique_ptr<T>(pointer)) 
     { 
     } 
    }; 
}; 
Các vấn đề liên quan