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 ==========
3 Answers 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.
Comments
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
operator==(string const &lhs, string const &rhs) somehow without the wrapper code?Hmm, try changing your functor args to bool operator()(const string & lhs, const string & rhs). See if that helps.
1 Comment
string const ¶m and const string ¶m are the same. But I've followed your advice and unfortunately nothing had changed :(
stringreallystd::string?"Hello"to a std::string in thestd::findcall. Pass your functor to thestd::findcall. As it stands currently, your functor will not be used in that call, it'll useoperator==. Also, could you post the entire build output (there's some additional diagnostics that appear to be missing).std::findalways useoperator==. The build output added to the original post.