#include <set>
#include <string>
#include <string_view>
using namespace std;
int main()
{
string_view key = "hello";
set<string> coll1;
coll1.find(key); // error
set<string, less<>> coll2;
coll2.find(key); // ok since C++14
}
Тогда, должно ли это быть правилом:
Всегда предпочитаю set<T, less<>>
в set<T>
начиная с C ++ 14?
Найти контрпример легко:
#include <set>
#include <string>
using namespace std;
struct converts_to_string {
operator string() const { return ""; }
};
int main()
{
converts_to_string key;
set<string> coll1;
coll1.find(key); // OK
set<string, less<>> coll2;
coll2.find(key); // error
}
Может быть снижение производительности при использовании associative_container<T, less<>>
: Рассмотреть тип как
#include <iostream>
#include <set>
#include <string>
struct stupid_string
{
stupid_string(char const* s)
: s(s)
{ std::cout << "copy\n"; }
stupid_string(char const* s, int) // silent
: s(s)
{}
friend bool operator<(stupid_string const& lhs, stupid_string const& rhs);
private:
std::string s;
};
bool operator<(stupid_string const& lhs, stupid_string const& rhs) {
return lhs.s < rhs.s;
}
int main() {
std::set<stupid_string, std::less<>> s;
s.emplace("hello", 0);
s.emplace("world", 0);
s.emplace("foobar", 0);
std::cout << "find\n";
(void)s.find("test");
}
Здесь приложение operator<
в алгоритме, выполняемом s.find
преобразует символьный литерал в stupid_string
неявно. Это происходит для каждого выполненного сравнения! Живая демо
Мне известен один случай, когда нечто подобное происходило в производственном коде с несоответствующей реализацией C ++ 03 StdLib.
Это, кстати, главная причина, почему гетерогенный поиск через less<>
был сделан по желанию; увидеть N3657:
Стефан Т. Лававей предположил, что две проблемы сохранения
существующее поведение и разрешение гетерогенных поисков могут быть
решается путем обнаружения контейнеров, когда объект сравнения
принимает разнородные аргументы и только условно перегружая
текущие функции поиска с версиями шаблона.