станд :: наборнельзя использовать std :: find (...) с - PullRequest
2 голосов
/ 09 января 2012

У меня есть следующий код, который не может быть скомпилирован:

#include <iostream>
#include <set>
#include <functional>
#include <cstring>

using namespace std;

struct StringCompareNoRegister: public binary_function<string, string, bool> {
  bool operator()(string const& lhs, string const& rhs) const {
    return (_stricmp(lhs.c_str(), rhs.c_str()) < 0);
  }
};

int wmain() {
  set<string, StringCompareNoRegister> s;
  s.insert("hello");
  s.insert("STL");
  s.insert("Hello");
  wcout << s.find("Hello")->c_str() << endl;
  wcout << find(s.begin(), s.end(), "Hello")->c_str() << endl;

  return 0;
}

CTP-компилятор MVCPP v.11 выкрикивает последнюю строку, где используется std::find:

Ошибка 1 Ошибка C2678: двоичный файл '==': не найден оператор, который принимает левый операнд типа 'const std :: basic_string <_Elem, _Traits, _Alloc> '(или нет приемлемого преобразование) c: \ программные файлы (x86) \ Microsoft Visual Studio 11.0 \ vc \ include \ xutility 3171

Почему я не могу скомпилировать этот код? Что я сделал не так?

ОБНОВЛЕНИЕ: полный вывод компилятора

1> ------ Начата сборка: Проект: Test01, Конфигурация: Отладка Win32 ------ 1> main.cpp 1> c: \ program files (x86) \ microsoft visual studio 11.0 \ vc \ include \ xutility (3171): ошибка C2678: двоичный файл '==': не найден оператор, который принимает левый операнд типа 'const std :: basic_string <_Elem, _Traits, _Alloc> '(или нет приемлемого преобразование) 1> с 1> [1> _Elem = char, 1> _Traits = std :: char_traits, 1>
_Alloc = std :: allocator 1>] 1> может быть «встроенным оператором C ++ == (const char [6], const char [6])» 1>
c: \ program files (x86) \ Microsoft Visual Studio 11.0 \ vc \ include \ exception (488): или 'bool std :: operator == (const std :: _ Exception_ptr &, const std :: _ Exception_ptr &)' 1>
c: \ program files (x86) \ Microsoft Visual Studio 11.0 \ vc \ include \ exception (493): или 'bool std :: operator == (std :: _ Null_type, const std :: _ Exception_ptr &)' 1> c: \ программные файлы (x86) \ microsoft visual studio 11.0 \ vc \ include \ exception (499): или 'bool std :: operator == (const std :: _ Exception_ptr &, std :: _ Null_type)' 1> c: \ программные файлы (x86) \ Microsoft Visual Studio 11.0 \ vc \ include \ system_error (419): или
'bool std :: operator == (const std :: error_code &, const std :: error_condition &) '1> c: \ program files (x86) \ microsoft Visual Studio 11.0 \ vc \ include \ system_error (427): или 'bool std :: operator == (const std :: error_condition &, const std :: error_code &) '1> c: \ program files (x86) \ Microsoft Visual Studio 11.0 \ vc \ include \ tuple (537): или 'bool std :: operator == (const std :: tuple <> &, const std :: tuple <> &)' 1> при попытке сопоставить список аргументов '(const std :: basic_string <_Elem, _Traits, _Alloc>, const char [6]) '1>
с 1> [1> _Elem = char, 1>
_Traits = std :: char_traits, 1> _Alloc = std :: allocator 1>] 1> c: \ программные файлы (x86) \ Microsoft Visual Studio 11.0 \ vc \ include \ xutility (3204): см. ссылка на экземпляр шаблона функции '_InIt станд :: _ Найти, Const char [6]> (_ InIt, _InIt, _Ty (&)) 'компилируется 1> с 1>
[1>
_Init = станд :: _ Tree_unchecked_const_iterator, станд :: Распределитель >>>>, 1>
_Mytree = станд :: _ Tree_val, станд :: Распределитель >>>, 1> _Ty = const char [6] 1>] 1>
d: \ docs \ Programming \ test01 \ test01 \ main.cpp (39): см. ссылку на создание экземпляра шаблона функции '_InIt станд :: найти, Const char [6]> (_ InIt, _InIt, _Ty (&)) 'компилируется 1> с 1>
[1>
_Init = станд :: _ Tree_const_iterator, станд :: Распределитель >>>>, 1>
_Mytree = станд :: _ Tree_val, станд :: Распределитель >>>, 1> _Ty = const char [6] 1>] ========== Построение: 0 выполнено, 1 не выполнено, 0 обновлено, 0 пропущено ==========

Ответы [ 3 ]

3 голосов
/ 10 января 2012

Ops. Точный ответ: я забыл добавить заголовок <string> для включений. Заголовок строки содержит внешние (не являющиеся членами) std::string функции сравнения, такие как operator==, operator< и т. Д.

Большое спасибо за ваши ответы.

2 голосов
/ 10 января 2012

std :: find не использует пользовательские компараторы таким же образом. Вам необходимо перегрузить оператор ==.

Поведение ожидается что-то вроде ниже. Проверьте cplusplus.com для справки.

template<class InputIterator, class T>
  InputIterator find ( InputIterator first, InputIterator last, const T& value )
  {
    for ( ;first!=last; first++) if ( *first==value ) break;
    return first;
  }

Таким образом, вы ожидаете что-то подобное, если используете пользовательский тип.

struct Foo {
    Foo(const std::string &s_) : s(s_) {}
    std::string s;
    // used by std::set<Foo, Foo::Less>::find
    struct Less {
        bool operator()(const Foo &lhs, const Foo &rhs) const {
            return lhs.s.compare(rhs.s) < 0;
        }
    };
};

// used by std::find
bool operator==(const Foo &lhs, const Foo &rhs) {
    return lhs.s.compare(rhs.s) == 0;
}

int main(int argc, char ** argv) {
    std::set<Foo, Foo::Less> foos;
    foos.insert(Foo("hello"));
    foos.insert(Foo("STL"));
    foos.insert(Foo("Hello"));

    std::cout << foos.find(Foo("Hello"))->s.c_str() << std::endl;
    std::cout << find(foos.begin(), foos.end(), Foo("Hello"))->s << std::endl;
    return 0;
}   

Linux только что нашел оператор для std :: string, поэтому я не смог проверить ваше конкретное поведение. Возможно, вам понадобится добавить несколько включений.

#include <algorithm>
#include <string>

В противном случае определение собственного довольно безболезненно.

bool operator==(const std::string &lhs, const std::string &rhs) {
    return lhs.compare(rhs) == 0;
}
0 голосов
/ 09 января 2012

Хм, попробуйте изменить аргументы функтора на bool operator()(const string & lhs, const string & rhs). Посмотрите, поможет ли это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...