Ответ 1
Вам нужно явно указать прозрачный компаратор (например, std::less<>
):
std::map<std::string, int, std::less<>> m;
// ~~~~~~~~~~^
std::map<K,V>
умолчанию использует свой компаратор: std::less<K>
(т.е. непрозрачный), и так как ([associative.reqmts]/p13):
Шаблоны функций-членов
find
,count
,lower_bound
,upper_bound
иequal_range
не должны участвовать в разрешении перегрузки, если квалифицированный идентификаторCompare::is_transparent
является допустимым и не обозначает тип (14.8.2).
функция-член шаблона find
не является подходящим кандидатом.
Гетерогенный сравнительный поиск для ассоциативных контейнеров был добавлен в c++14. Первоначальное предложение рисковало нарушить существующий код. Например:
c.find(x);
семантически эквивалентно:
key_type key = x;
c.find(key);
В частности, преобразование между x
и key_type
происходит только один раз и перед фактическим вызовом.
Гетерогенный поиск заменяет это преобразование в пользу сравнения между key
и x
. Это может привести к снижению производительности в существующем коде (из-за дополнительного преобразования перед каждым сравнением) или даже к прерыванию компиляции (если оператор сравнения является функцией-членом, он не будет применять преобразование для левого операнда):
#include <set>
#include <functional>
struct A
{
int i;
A(int i) : i(i) {}
};
bool operator<(const A& lhs, const A& rhs)
{
return lhs.i < rhs.i;
}
int main()
{
std::set<A, std::less<>> s{{1}, {2}, {3}, {4}};
s.find(5);
}
Для решения этой проблемы было добавлено новое поведение путем добавления концепции прозрачных компараторов, как описано в связанном вопросе.