4

I'm trying to compile a small COM dll (using visual studio 2008 pro), and it compiles fine in release, but when I try to compile it in debug I get a compilation error:

error C2664: 'bool (MyClass &, double)': cannot convert parameter 2 from 'MyClass' to 'double'.

Now this error comes from a line in the code where I do this (note that someValueThatIsADouble is of type double):

std::vector<MyClass>::iterator iter = std::lower_bound(MyVector.begin(), MyVector.end(), someValueThatIsADouble, less);

And the less function is defined this way:

bool less(MyClass& a, double b);

I don't understand why I get this error, and if there is a good reason for this error, why do I only get it in Debug (and not in Release)? The dll, when compiled in Release, runs fine and doesn't crash. Also, I checked and there is no #ifdef DEBUG or things like that which could change the code that is compiled in debug and in release.

EDIT:

I didn't write the code myself and it is an algorithm I don't know much about so I don't know what the double value is supposed to represent and I don't want to go change the logic inside the less function to take a MyClass instead of a double as a second parameter.

class MyClass
{
public :
    MyClass(): _dValue1(0.0),_dValue2(0.0),_dValue3(0.0)
    {
    }
    MyClass(double dValue1, double dValue3, double dValue2): _dValue2(dValue2),_dValue3(dValue3),_dValue1(dValue1)
    {
    }
    ~MyClass() {}
    double getValue1() {return _dValue1;}
    double getValue3() {return _dValue3;}
    double getValue2() {return _dValue2;}
    double _dValue1;
    double _dValue3;
    double _dValue2;

public:

    friend class vector<MyClass>; 


int compare(const MyClass & t1, const MyClass & t2)
{
  if (t1._dValue1 < t2._dValue1)
    return -1;
  else if (t2._dValue1 < t1._dValue1)
    return 1;
  else
    return 0;
}

bool operator> (const MyClass & rhs)
{
    if (  _dValue1 > rhs._dValue1)
        return true;
    else 
        return false;
}

bool operator< (const MyClass & rhs)
{
    if (  _dValue1 < rhs._dValue1)
        return true;
    else 
        return false;
}

};

Edit:

MSalters' answer showed that the debug and release implementations of the predicates weren't the same, which made it compile in release and not in debug in my case (because the code isn't very neat and should not use a comparison function with 2 different types). The hack I did to be able to use this code in debug also was to put this line before any includes (note that the preferred solution should be to have a better comparison function, but in my case it wasn't possible):

#define _HAS_ITERATOR_DEBUGGING 0 
Carl
  • 1,224
  • 2
  • 19
  • 35

3 Answers3

2

The error message suggests you're using MSVC. It's library implementation contains debug checks on predicates. In particular, for a partial order predicate (such as your less), I think it tests whether Pred(a,b) && Pred(b,a) == false. Obviously that won't work here.

(One of the common errors with predicates is that people used to define an order such that both a<b and b<a. There are many <algorithm>s that break down in that case, which is why there are now some debug checks to prevent such errors. Still they only catch errors if you actually manage to pass a pair of bad a,b values at runtime; they can't catch theoretical errors at compile time)

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • Ah yeah that's very possible, thanks! So is there some way (probably a hack) I could make it build in debug using the code provided or I must absolutely try to figure out how to write the correct operator? – Carl Jul 18 '11 at 13:28
  • 1
    This should never work, because it will evaluate to false whenever a == b. However, maybe it tests something like Pred(a, b) => !Pred(b, b) – b.buchhold Jul 18 '11 at 13:31
  • The STL error checking is intended to find errors like yours; you could turn just that off. See MSDN for details. (Debug and release are really just predefined set of options. You can generally tweak them. E.g. Most professionals built .PDB files for release builds, too) – MSalters Jul 18 '11 at 13:33
  • @ b.buchhold: Oops, got the anti-reflexive test wrong from memory. Inverted. The logic is that you can't have both `a – MSalters Jul 18 '11 at 13:35
  • In my case, even though our Release configuration builds PDB files, it still does not show all the errors that we get in Debug configuration. In particular, in Debug builds only we get this error: Error C4716 [function template name here] must return a value. I would very much like to learn how to make our Release configuration show the same errors as Debug. – Scott Hutchinson Jan 23 '17 at 22:43
1

Try with :

bool less(const MyClass& a, const MyClass& b);
iammilind
  • 68,093
  • 33
  • 169
  • 336
rlods
  • 465
  • 2
  • 6
  • I should have mentioned that I don't want to change the less function. Just edited my question. – Carl Jul 18 '11 at 13:17
  • The less function provided to lower_bound call is used to compare two items of the given collection : since the collection is a collection of MyClass, the less function must take two references to MyClass instances. Could you provide the declaration of MyClass, maybe there are some specific operators defined on it. – rlods Jul 18 '11 at 13:19
  • That was my thought at first too, but if so why does it compile in release mode? – Carl Jul 18 '11 at 13:21
  • Because there are probably some cast operators defined in the class declaration ... you should provide the MyClass declaration. – rlods Jul 18 '11 at 13:23
  • someValueThatIsADouble is of type double ? – rlods Jul 18 '11 at 13:30
1
template<class ForwardIterator, class Type, class BinaryPredicate>
ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const Type& val, BinaryPredicate comp);

first : A forward iterator addressing the position of the first element in the range to be searched.

last : A forward iterator addressing the position one past the final element in the range to be searched.

val : The value whose first position or possible first position is being searched for in the ordered range.

comp : User-defined predicate function object that defines sense in which one element is less than another. A binary predicate takes two arguments and returns true when satisfied and false when not satisfied.

It compiles in release because some checks are deactivated in release implementation of std. But it should not compile : val should be of type MyClass and not of type double and then less won't compile anymore even in release.

rlods
  • 465
  • 2
  • 6