#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
template<typename Map, typename K>
auto tolerant_find(const Map & map, const K & lookup, const K & tolerance) -> decltype(map.begin()) {
// Assuming (first,last) is a sorted sequence of pairs
// First, find sub-sequence of keys "near" the lookup value
auto first = map.lower_bound(lookup - tolerance);
auto last = map.upper_bound(lookup + tolerance);
// If they are equal, the sequence is empty, and thus no entry was found.
// Return the end iterator to be consistent with std::find.
if (first == last) {
return map.end();
}
// Then, find the one with the minimum distance to the actual lookup value
typedef typename Map::mapped_type T;
return std::min_element(first, last, [lookup](std::pair<K,T> a, std::pair<K,T> b) {
return std::abs(a.first - lookup) < std::abs(b.first - lookup);
});
}
int main() {
std::map<float,int> mymap = {
{ 1.0, 1 },
{ 5.0, 2 },
{ 5.1, 3 },
{ 5.11, 4 },
{ 5.2, 5 }
};
// This should find the key 5.11
cout << tolerant_find(mymap, 5.15, 0.1)->first << endl;
// This should find the key 5.2
cout << tolerant_find(mymap, 5.16, 0.1)->first << endl;
// This should print "not found".
cout << (tolerant_find(mymap, 2.0, 0.1) == mymap.end() ? "not found" : "found") << endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8bWFwPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKdGVtcGxhdGU8dHlwZW5hbWUgTWFwLCB0eXBlbmFtZSBLPgphdXRvIHRvbGVyYW50X2ZpbmQoY29uc3QgTWFwICYgbWFwLCBjb25zdCBLICYgbG9va3VwLCBjb25zdCBLICYgdG9sZXJhbmNlKSAtPiBkZWNsdHlwZShtYXAuYmVnaW4oKSkgewogICAgLy8gQXNzdW1pbmcgKGZpcnN0LGxhc3QpIGlzIGEgc29ydGVkIHNlcXVlbmNlIG9mIHBhaXJzCgogICAgLy8gRmlyc3QsIGZpbmQgc3ViLXNlcXVlbmNlIG9mIGtleXMgIm5lYXIiIHRoZSBsb29rdXAgdmFsdWUKICAgIGF1dG8gZmlyc3QgPSBtYXAubG93ZXJfYm91bmQobG9va3VwIC0gdG9sZXJhbmNlKTsKICAgIGF1dG8gbGFzdCA9IG1hcC51cHBlcl9ib3VuZChsb29rdXAgKyB0b2xlcmFuY2UpOwogICAgCiAgICAvLyBJZiB0aGV5IGFyZSBlcXVhbCwgdGhlIHNlcXVlbmNlIGlzIGVtcHR5LCBhbmQgdGh1cyBubyBlbnRyeSB3YXMgZm91bmQuCiAgICAvLyBSZXR1cm4gdGhlIGVuZCBpdGVyYXRvciB0byBiZSBjb25zaXN0ZW50IHdpdGggc3RkOjpmaW5kLgogICAgaWYgKGZpcnN0ID09IGxhc3QpIHsKICAgIAlyZXR1cm4gbWFwLmVuZCgpOwogICAgfQoKICAgIC8vIFRoZW4sIGZpbmQgdGhlIG9uZSB3aXRoIHRoZSBtaW5pbXVtIGRpc3RhbmNlIHRvIHRoZSBhY3R1YWwgbG9va3VwIHZhbHVlCiAgICB0eXBlZGVmIHR5cGVuYW1lIE1hcDo6bWFwcGVkX3R5cGUgVDsKICAgIHJldHVybiBzdGQ6Om1pbl9lbGVtZW50KGZpcnN0LCBsYXN0LCBbbG9va3VwXShzdGQ6OnBhaXI8SyxUPiBhLCBzdGQ6OnBhaXI8SyxUPiBiKSB7CiAgICAgICAgcmV0dXJuIHN0ZDo6YWJzKGEuZmlyc3QgLSBsb29rdXApIDwgc3RkOjphYnMoYi5maXJzdCAtIGxvb2t1cCk7CiAgICB9KTsKfQoKaW50IG1haW4oKSB7CglzdGQ6Om1hcDxmbG9hdCxpbnQ+IG15bWFwID0gewoJCXsgMS4wLCAxIH0sCgkJeyA1LjAsIDIgfSwKCQl7IDUuMSwgMyB9LAoJCXsgNS4xMSwgNCB9LAoJCXsgNS4yLCA1IH0KCX07CgkKCS8vIFRoaXMgc2hvdWxkIGZpbmQgdGhlIGtleSA1LjExCgljb3V0IDw8IHRvbGVyYW50X2ZpbmQobXltYXAsIDUuMTUsIDAuMSktPmZpcnN0IDw8IGVuZGw7CgkvLyBUaGlzIHNob3VsZCBmaW5kIHRoZSBrZXkgNS4yCgljb3V0IDw8IHRvbGVyYW50X2ZpbmQobXltYXAsIDUuMTYsIDAuMSktPmZpcnN0IDw8IGVuZGw7CgkKCS8vIFRoaXMgc2hvdWxkIHByaW50ICJub3QgZm91bmQiLgoJY291dCA8PCAodG9sZXJhbnRfZmluZChteW1hcCwgMi4wLCAwLjEpID09IG15bWFwLmVuZCgpID8gIm5vdCBmb3VuZCIgOiAiZm91bmQiKSA8PCBlbmRsOwoJCglyZXR1cm4gMDsKfQ==