Reputation: 7863
I have a Visual Studio 2008 C++03 application where I would like to create a std::map
that uses the iterator from another std::map
as its key-type. But, I run in to a problem when I try to erase an element from that map using its key-type.
In this example, when an element in MyList
gets to be more than 5 minutes old, a timer should fire and removes it from the map and destroy its age-timer.
typedef std::map< Foo, FooBar > MyList;
typedef std::map< MyList::iterator, boost::shared_ptr< Timer > > MyListAgeTimers;
class A
{
public:
void AddItem( Foo& f, FooBar& fb )
{
CriticalSection::Guard g( lock_ );
std::pair< MyList::iterator, bool > new_foo =
my_list_.insert( std::make_pair( f, fb ) );
if( new_foo.second )
{
timers_.insert( std::make_pair(
new_foo.first,
boost::make_shared< Timer >( FiveMinutes, boost::bind( &A::OnAgeTimer, this, new_foo.first ) ) ) );
}
};
void OnAgeTimer( MyList::iterator item )
{
CriticalSection::Guard g( lock_ );
// erase by key-type generates an error:
// functional(143) : error C2676: binary '<' : 'const std::_Tree<_Traits>::iterator' does not define this operator or a conversion to a type acceptable to the predefined operator
timers_.erase( item );
// erase by iterator. works okay.
my_list_.erase( item );
};
private:
MyList my_list_;
MyListAgeTimers timers_;
CriticalSection lock_;
};
Can you not use the iterator from one map as the key-type to another? Or, do I need to define a specialized operator<
for this?
EDIT:
The obvious thing to do (to me) is just this:
namespace std {
inline bool operator <( const MyList::iterator& a, const MyList::iterator& b )
{
return a->first < b->first;
}
};
But, if that's correct, why is that not the default behavior for the std::operator<
when comparing two iterators?
Upvotes: 1
Views: 360
Reputation: 76428
std::map<key, value>
requires that key
have an operator<
; that's what the map object uses to find a matching key. std::map<x, y>::iterator
is a bidirectional iterator; it does not have an operator<
, so you can't use it as the key type in another map unless you provide your own operator<
or a function object to compare two iterators and decide which one comes before the other.
Upvotes: 6