с C++14 нам разрешено сравнивать элементы некоторых ассоциативных контейнеров (например, std::set) с другими типами, кроме тех, которые хранятся в контейнере. Это должно работать, когда компаратор имеет is_transparent
, обозначенный как тип (см., например, std::set::find а>).
Предположим, у меня есть оболочка строки, которая выполняет некоторые проверки строки (если ее формат является допустимым форматом и т. д. - не очень важно, но ее создание достаточно тяжелое, и я хотел бы избежать этого + он может генерировать исключения), и это хранится в std::set, чтобы иметь контейнер уникальных значений. Как мне написать для него компаратор? Должен ли он выглядеть так, как показано ниже? Могу ли я перегрузить и использовать свой sw::operator<()
для достижения того же?
class sw
{
public:
explicit sw(const std::string& s) : s_(s) { /* dragons be here */ }
const std::string& getString() const { return s_; }
bool operator<(const sw& other) const { return s_ < other.s_; }
private:
std::string s_;
};
struct Comparator
{
using is_transparent = std::true_type;
bool operator()(const sw& lhs, const std::string& rhs) const { return lhs.getString() < rhs; }
bool operator()(const std::string& lhs, const sw& rhs) const { return lhs < rhs.getString(); }
bool operator()(const sw& lhs, const sw& rhs) const { return lhs < rhs; }
};
int main()
{
std::set<sw, Comparator> swSet{ sw{"A"}, sw{"B"}, sw{"C"} };
std::cout << std::boolalpha << (swSet.find(std::string("A")) != swSet.end()) << std::endl;
}
Я считаю, что приведенный выше код должен работать, как и ожидалось, но когда я тестировал его с помощью g++ 4.9 и clang++ 3.6, оба выдавали ошибки об отсутствии преобразования из string
в key_type
, как будто перегрузки строк Comparator::operator()
никогда не учитывались. Я что-то упускаю?