std::function is only comparable against nullptr_t see here
For this reason I would use a solution similar to the one provided here below, where the returned object unmaps during destruction by using the iterator. One of course then requires a container who's iterators are not invalidated. A variety of similar idioms can be written, and an attempt can be made at making it entirely generic. I've just provided the idea though (following here below):
As map iterators aren't invalidated when inserting, I usually return an object that wraps the iterator, and unmaps by using the iterator when going out of scope:
It looks something like this...
struct Resource{ virtual ~Resource(){} };
template <class SubjectT, class IterT>
struct Unmapper : Resource
{
typedef void (SubjectT::*UnmapFunc)( IterT );
Unmapper(
std::shared_ptr<SubjectT> subject, UnmapFunc unmap, IterT ref )
: subject_( subject ), ref_( ref ), unmap_( unmap )
{
}
~Unmapper()
{
std::shared_ptr<SubjectT> subject = subject_.lock();
if( subject ){ ((*subject).*unmap_)( ref_ ); }
}
private:
std::weak_ptr<SubjectT> subject_;
IterT ref_;
UnmapFunc unmap_;
};
template <class SubjectT, class IterT>
std::unique_ptr<Resource> makeUnmapper( std::shared_ptr<SubjectT> subject,
void (SubjectT::*unmapFunc)( IterT ), IterT ref )
{
return std::unique_ptr<Resource>(
new Unmapper<SubjectT, IterT>( subject, unmapFunc, ref ) );
}
... and ...
//Could generalise by using variadic templates, yes...
class Subject : public std::enable_shared_from_this
{
public:
typedef std::function<void()> my_function;
std::unique_ptr<Resource> subscribe( int id, my_function func )
{
//psuedo code...
my_map::iterator pos = myMap_.insert( id, func );
if( pos.second )
{
return makeUnmapper( shared_from_this(), &Subject::unmap, pos );
}
else throw already_subscribed();
}
private:
//etc... declare map etc...
void unmap( my_map::iterator pos ){ myMap_.erase( pos ); }
};
Note:
I have not compiled this. I might have missed a move, but I doubt it, as the unique_ptr's are always rvalues.