0

I am facing troubles to compile in debug mode some code that uses std::lower_bound() function in combination with a comparison operator.

I have isolated the error in a small code snippet that I attach hereafter:

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

using namespace std;

struct SPippo
{
  SPippo(string rsName, int rnValue);

  static const bool compareId(const SPippo& lhs, const int& rId){return lhs.iValue < rId;}

  string sName;
  int iValue;
};


SPippo::SPippo(string rsName, int riValue):
  sName(rsName)
,iValue(riValue)
{ 
}

struct sOrd
{
  const bool operator() (const SPippo& lhs, const int& rId) const {return SPippo::compareId(lhs, rId);}
  const bool operator() (const int& rId, const SPippo& lhs) const {return SPippo::compareId(lhs, rId);}
};

int main()
{

  vector<SPippo> vecPippo;
  vecPippo.push_back(SPippo("Minnie", 1));
  vecPippo.push_back(SPippo("Paperino", 2));
  vecPippo.push_back(SPippo("Pippo", 3));
  vecPippo.push_back(SPippo("Topolino", 4));

  vector<SPippo>::const_iterator cItLowerBound = std::lower_bound(vecPippo.begin(), vecPippo.end(), 2, sOrd());

  return 0;
}

I am using VS2008 to compile: when using release configuration everything works fine. Instead, in debug mode I get the following errors:

1>c:\program files (x86)\microsoft visual studio 9.0\vc\include\xutility(346) : error C2664: 'const bool sOrd::operator ()(const int &,const SPippo &) const' : cannot convert parameter 1 from 'SPippo' to 'const int &'
1>        Reason: cannot convert from 'SPippo' to 'const int'
1>        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\xutility(1699) : see reference to function template instantiation 'bool std::_Debug_lt_pred<_Pr,SPippo,SPippo>(_Pr,_Ty1 &,_Ty2 &,const wchar_t *,unsigned int)' being compiled
1>        with
1>        [
1>            _Pr=sOrd,
1>            _Ty1=SPippo,
1>            _Ty2=SPippo
1>        ]
1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\xutility(1709) : see reference to function template instantiation 'void std::_Debug_order_single2<_InIt,_Pr>(_FwdIt,_FwdIt,_Pr,bool,const wchar_t *,unsigned int,std::forward_iterator_tag)' being compiled
1>        with
1>        [
1>            _InIt=std::_Vector_iterator<SPippo,std::allocator<SPippo>>,
1>            _Pr=sOrd,
1>            _FwdIt=std::_Vector_iterator<SPippo,std::allocator<SPippo>>
1>        ]
1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\algorithm(2290) : see reference to function template instantiation 'void std::_Debug_order_single<_FwdIt,_Pr>(_InIt,_InIt,_Pr,bool,const wchar_t *,unsigned int)' being compiled
1>        with
1>        [
1>            _FwdIt=std::_Vector_iterator<SPippo,std::allocator<SPippo>>,
1>            _Pr=sOrd,
1>            _InIt=std::_Vector_iterator<SPippo,std::allocator<SPippo>>
1>        ]
1>        c:\program files (x86)\microsoft visual studio 9.0\vc\include\algorithm(2314) : see reference to function template instantiation '_FwdIt std::_Lower_bound<std::_Vector_iterator<_Ty,_Alloc>,int,__w64 int,_Pr>(_FwdIt,_FwdIt,const int &,_Pr,_Diff *)' being compiled
1>        with
1>        [
1>            _FwdIt=std::_Vector_iterator<SPippo,std::allocator<SPippo>>,
1>            _Ty=SPippo,
1>            _Alloc=std::allocator<SPippo>,
1>            _Pr=sOrd,
1>            _Diff=__w64 int
1>        ]
1>        c:\users\cgab\documents\visual studio 2008\projects\sweettest\sweettest\main.cpp(42) : see reference to function template instantiation '_FwdIt std::lower_bound<std::_Vector_iterator<_Ty,_Alloc>,int,sOrd>(_FwdIt,_FwdIt,const int &,_Pr)' being compiled
1>        with
1>        [
1>            _FwdIt=std::_Vector_iterator<SPippo,std::allocator<SPippo>>,
1>            _Ty=SPippo,
1>            _Alloc=std::allocator<SPippo>,
1>            _Pr=sOrd
1>        ]
1>c:\program files (x86)\microsoft visual studio 9.0\vc\include\xutility(348) : error C2664: 'const bool sOrd::operator ()(const int &,const  SPippo &) const' : cannot convert parameter 1 from 'SPippo' to 'const int &'
1>        Reason: cannot convert from 'SPippo' to 'const int'
1>        No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>Build log was saved at "file://c:\Users\cgab\Documents\Visual Studio 2008\Projects\SweetTest\SweetTest\Debug\BuildLog.htm"
1>SweetTest - 2 error(s), 0 warning(s)

When using VS2015 or higher, the code compiles fine also in debug mode. Given that I am forced to use VS2008 for my project, do you think there is a way to solve this issue without giving up on the usage of lower_bound()?

Thank you in advance for your assistance!

I think the problem is in the code used by VS2008 in xutility. In fact, the error points to the following excerpt:

template<class _Pr, class _Ty1, class _Ty2> inline
bool __CLRCALL_OR_CDECL _Debug_lt_pred(_Pr _Pred, const _Ty1& _Left,     const _Ty2& _Right,
const wchar_t *_Where, unsigned int _Line)
{   // test if _Pred(_Left, _Right) and _Pred is strict weak ordering
if (!_Pred(_Left, _Right))
    return (false);
else if (_Pred(_Right, _Left))
    _DEBUG_ERROR2("invalid operator<", _Where, _Line);
return (true);

So, a single Pred function is tested inverting the order of parameters. But this works if the predicate accepts parameters of the same type, otherwise not!

This specific part of source code xutility in VS2010 is not executed because of a default setting of _ITERATOR_DEBUG_LEVEL, defined in C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\yvals.h. This probably explains why the code compiles in other versions of VS other than VS2008.

3
  • 1
    Your example compiles on both g++ and clang++. Commented Dec 15, 2017 at 15:31
  • Also compiles on VS 2010. Which doesn't have a C++11 support like VS 2008. Commented Dec 15, 2017 at 15:33
  • Unrelated to your debug problem, a few suggestions: 1) I think one of the two () operators should return a negation of the compare function, because the operands are swapped. I.e. if lessthan(a,b) is true, lessthan(b,a) cannot also be true. 2) There is no point in using const int&. Int is sufficient. 3) No point in returning const bool. Bool is sufficient. Commented Dec 15, 2017 at 16:29

1 Answer 1

0

In case someone else stumbles across this, a "hack" to workaround this is to disable iterator debugging for the respective compilation unit. The following code snipped, if placed before the #include directives, does this:

#if defined(_MSC_VER) && defined(_DEBUG) && _MSC_VER <= 1500
#define _HAS_ITERATOR_DEBUGGING 0
#endif
Sign up to request clarification or add additional context in comments.

Comments

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.