Всегда предпочитайте set & lt; T, less & lt; & gt; & gt; установить & lt; T & gt; начиная с C ++ 14?

#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?

29

Решение

Найти контрпример легко:

#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
}
19

Другие решения

Может быть снижение производительности при использовании 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:

Стефан Т. Лававей предположил, что две проблемы сохранения
существующее поведение и разрешение гетерогенных поисков могут быть
решается путем обнаружения контейнеров, когда объект сравнения
принимает разнородные аргументы и только условно перегружая
текущие функции поиска с версиями шаблона.

10