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

Почему не используется std:: find() с помощью моего оператора ==?

В следующем фрагменте кода я перегрузил operator==, чтобы сравнить мой тип пары со строкой. Но по какой-то причине компилятор не находит мой оператор в качестве соответствия функции поиска. Почему бы и нет?

Изменить: Спасибо за все предложения по альтернативам, но я все равно хотел бы понять, почему. Код выглядит так, как будто он должен работать; Я хотел бы знать, почему это не так.

#include <vector>
#include <utility>
#include <string>
#include <algorithm>

typedef std::pair<std::string, int> RegPair;
typedef std::vector<RegPair> RegPairSeq;

bool operator== (const RegPair& lhs, const std::string& rhs)
{
    return lhs.first == rhs;
}

int main()
{
    RegPairSeq sequence;
    std::string foo("foo");
    // stuff that not important
    std::find(sequence.begin(), sequence.end(), foo);
    // g++: error: no match for 'operator==' in '__first. __gnu_cxx::__normal_iterator<_Iterator, _Container>::operator* [with _Iterator = std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>*, _Container = std::vector<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int>, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int> > >]() == __val'
    // clang++: error: invalid operands to binary expression ('std::pair<std::basic_string<char>, int>' and 'std::basic_string<char> const')
}
4b9b3361

Ответ 1

Проблема заключается в том, что std::find является шаблоном функции, и он использует зависящий от аргумента поиск (ADL), чтобы найти правильный operator== для использования.

Оба аргумента находятся в пространстве имен std (std::pair<std::string, int> и std::string), поэтому ADL начинается с поиска в пространстве имен std. Там он найдет несколько operator== (один, это не имеет значения, в стандартной библиотеке есть партии, и если вы включили <string>, можно найти по крайней мере тот, который сравнивает два объекта std::basic_string<T>).

Поскольку в пространстве имен std обнаружена перегрузка operator==, ADL перестает искать охватывающие области. Ваша перегрузка, которая находится в глобальном пространстве имен, никогда не будет найдена. Поиск имени происходит до разрешения перегрузки; во время поиска имени не имеет значения, соответствуют ли аргументы.

Ответ 2

Самое чистое решение - сделать предикат и использовать find_if:

struct StringFinder
{
  StringFinder(const std::string & st) : s(st) { }
  const std::string s;
  bool operator()(const RegPair& lhs) const { return lhs.first == s; }
}

std::find_if(sequence.begin(), sequence.end(), StringFinder(foo));

Если у вас есть С++ 11, вы можете использовать лямбда вместо этого.

Ответ 3

Другое "правильное" решение:

struct RegPair : std::pair<std::string, int>
{
    bool operator== (const std::string& rhs) const;
};

bool RegPair::operator== (const std::string& rhs) const
{
    return first == rhs;
}