Yes, use standard operator< in a set or a map. Most fuzzy double comparators are not strict enough to be used in a map or set. (And hope to hell that you aren't messing around with floating point modes while accessing said map...)
I would advise to use multimap or multiset, because two values you think are equal might be slightly different. If you are already expecting multiple entries, you should handle almost-equal entries much better.
Next, when searching for a hit do lower_bound(x - epsilon) and upper_bound(x + epsilon) in order to catch entries in the map that aren't where you think they are.
Ie, here is "is this double in this multiset<double>" code:
typedef std::multiset<double> double_set;
std::pair< double_set::iterator, double_set::iterator >
get_equal_range( double_set& s, double d, double epsilon = 0.00001 )
{
auto lower = s.lower_bound( d-epsilon );
auto upper = s.upper_bound( d+epsilon );
return std::make_pair( lower, upper );
}
std::pair< double_set::const_iterator, double_set::const_iterator >
get_equal_range( double_set const& s, double d, double epsilon = 0.00001 )
{
auto lower = s.lower_bound( d-epsilon );
auto upper = s.upper_bound( d+epsilon );
return std::make_pair( lower, upper );
}
bool TestMembership( double_set const& s, double d, double epsilon = 0.00001 )
{
auto range = get_equal_range( s, d, epsilon );
return range.first != range.second;
}
So a given double could map to a range of entries, or have more than 1 hit in the set.
Stolen from a great answer below: Default double operator< will screw your map or set up if you pass NaN in.
When putting things into map and set (and multi versions), you must maintain the strict weak ordering rules. If you fail, you will get seemingly random crashes, and the occasional infinite loop: the code in map and set is not robust against ordering failure.