Подтвердить что ты не робот

Всегда предпочитайте set <T, less <>> для установки <T>, так как С++ 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> , так как С++ 14?

4b9b3361

Ответ 1

Тривиально найти контрпример:

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

Ответ 2

При использовании 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. Это происходит для каждого проведенного сравнения! Живая демонстрация

Я знаю один случай, когда что-то подобное произошло в производственном коде с несоответствующей реализацией С++ 03 StdLib.


Это, кстати, основная причина, по которой неоднородный поиск через less<> был сделан opt-in; см. N3657:

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