2

I have the following code that cannot be compiled:

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

MVCPP v.11 CTP compiler yelling on the last line where std::find is used:

Error 1 error C2678: binary '==' : no operator found which takes a left-hand operand of type 'const std::basic_string<_Elem,_Traits,_Alloc>' (or there is no acceptable conversion) c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility 3171

Why I cannot compile this code? What have I done wrong?

UPDATE: Full compiler output

1>------ Build started: Project: Test01, Configuration: Debug Win32 ------ 1> main.cpp 1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(3171): error C2678: binary '==' : no operator found which takes a left-hand operand of type 'const std::basic_string<_Elem,_Traits,_Alloc>' (or there is no acceptable conversion) 1> with 1> [ 1> _Elem=char, 1> _Traits=std::char_traits, 1>
_Alloc=std::allocator 1> ] 1> could be 'built-in C++ operator==(const char [6], const char [6])' 1>
c:\program files (x86)\microsoft visual studio 11.0\vc\include\exception(488): or '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): or 'bool std::operator ==(std::_Null_type,const std::_Exception_ptr &)' 1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\exception(499): or 'bool std::operator ==(const std::_Exception_ptr &,std::_Null_type)' 1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\system_error(419): or
'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): or '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): or 'bool std::operator ==(const std::tuple<> &,const std::tuple<> &)' 1> while trying to match the argument list '(const std::basic_string<_Elem,_Traits,_Alloc>, const char [6])' 1>
with 1> [ 1> _Elem=char, 1>
_Traits=std::char_traits, 1> _Alloc=std::allocator 1> ] 1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(3204) : see reference to function template instantiation '_InIt std::_Find,const char[6]>(_InIt,_InIt,_Ty (&))' being compiled 1> with 1>
[ 1>
_InIt=std::_Tree_unchecked_const_iterator,std::allocator>>>>, 1>
_Mytree=std::_Tree_val,std::allocator>>>, 1> _Ty=const char [6] 1> ] 1>
d:\docs\programming\test01\test01\main.cpp(39) : see reference to function template instantiation '_InIt std::find,const char[6]>(_InIt,_InIt,_Ty (&))' being compiled 1> with 1>
[ 1>
_InIt=std::_Tree_const_iterator,std::allocator>>>>, 1>
_Mytree=std::_Tree_val,std::allocator>>>, 1> _Ty=const char [6] 1> ] ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

7
  • Strange. After adding appropriate headers, etc., this works for me with GCC. Commented Jan 9, 2012 at 17:01
  • It seems that something wrong with MVCPP11 STL realization (or compiler)... Commented Jan 9, 2012 at 17:06
  • Please post the full code. Is string really std::string? Commented Jan 9, 2012 at 17:51
  • 1
    Couple of things to try: explicitly convert "Hello" to a std::string in the std::find call. Pass your functor to the std::find call. As it stands currently, your functor will not be used in that call, it'll use operator==. Also, could you post the entire build output (there's some additional diagnostics that appear to be missing). Commented Jan 9, 2012 at 18:59
  • @NathanErnst explicit conversion didn't help. std::find always use operator==. The build output added to the original post. Commented Jan 9, 2012 at 21:26

3 Answers 3

3

Ops. The precise answer is that I've forgotten to add <string> header to includes. String header contains external (non-member) std::string comparison functions like operator==, operator<, etc.

Thank you very much for your answers.

Sign up to request clarification or add additional context in comments.

Comments

2

std::find does not use custom comparators in the same way. You need to overload the == operator.

The behavior is expected something like the below. Check cplusplus.com for the reference.

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

So you would expect something like this if you were using a custom type.

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 just found the operator for std::string, so I couldn't test your specific behavior. You may need to add some includes.

#include <algorithm>
#include <string>

Otherwise, defining your own is pretty painless.

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

1 Comment

Thanks Tom. Please, clarify: can I define operator==(string const &lhs, string const &rhs) somehow without the wrapper code?
0

Hmm, try changing your functor args to bool operator()(const string & lhs, const string & rhs). See if that helps.

1 Comment

string const &param and const string &param are the same. But I've followed your advice and unfortunately nothing had changed :(

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.