How to remove unique_ptr with a pointer from a container?

Creating an object and granting ownership of a container using unique_ptr is not a problem. How to delete an item using a raw pointer?

std::set<std::unique_ptr<MyClass>> mySet; MyClass *myClass = new MyClass(); mySet.insert(std::unique_ptr<MyClass>(myClass)); // remove myClass from mySet? 
+7
source share
4 answers

You will need to find the iterator that matches the myClass element, and then pass that iterator to mySet.erase() . An iterator can be found using the std::find_if with a custom functor Predicate that understands how to unique_ptr and compare it with the raw myClass pointer.

You cannot use the overloaded size_t set::erase ( const key_type& x ); since the raw pointer (even if it is wrapped in a temporary unique_ptr ) will not be found in mySet .

+3
source

Not as beautiful as we would like. But the following work:

 #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); } 
+3
source

It seems I can get an iterator using a special Predicate with lower_bound. Since std :: set is an ordered container, lower_bound should execute 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; } } 
+1
source

Still not the best solution, but for now I go:

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

Title:

 #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)) { } }; }; 
0
source

All Articles