1st of all, yes, I am stuck using Visual Studio 2008, and I believe this bug is specific to Visual Studio 2008.
I'm trying to write a functor to compare just 1 member of my struct so I can do upper_bound
on a vector
of said structs which is sorted by that member. That's hard to explain in words so here's an example:
struct Foo {
int a;
char b;
};
struct comp : binary_function<const double, const Foo&, bool> {
bool operator () (const double lhs, const Foo& rhs) { return lhs < rhs.a; }
};
int main() {
vector<Foo> test;
for(int i = 0; i < 5; ++i) {
Foo foo = { i + 1, 'a' + i };
test.push_back(foo);
}
cout << upper_bound(test.begin(), test.end(), 2, comp())->b << endl;
}
This works fine on Visual Studio 2015. But Visual Studio 2008 gives me the error:
error C2664: 'bool comp::operator ()(const double,const Foo &)' : cannot convert parameter 1 from 'Foo' to 'const double'
I suspect that there is some evil in the implementation where the functor is tested for strict weak ordering by swapping the inputs. Is there a workaround to suspend that checking on the compiler, or do I just have to just change my functor to taking in 2 Foo
s and make a temporary Foo
to represent the 2 here?
As stated by Algirdas Preidžius this is a Debug only implementation error in Visual Studio 2008. It has been corrected on visual-studio-2010.
The bug is in Microsoft's C++ implementation code and it's gated by _HAS_ITERATOR_DEBUGGING
so if disabling that is an option consider adding "_HAS_ITERATOR_DEBUGGING=0" to your "Preprocessor Definitions".
If you don't like the idea of disabling iterator checking you'll need to workaround by disabling _HAS_ITERATOR_DEBUGGING
so your code will look something like:
struct Foo {
int a;
char b;
};
int main() {
vector<Foo> test;
for(int i = 0; i < 5; ++i) {
Foo foo = { i + 1, 'a' + i };
test.push_back(foo);
}
#if _HAS_ITERATOR_DEBUGGING
for(vector<Foo>::const_iterator it = test.begin(); it != test.end(); ++it) {
if(it->a > 2) {
cout << it->b << endl;
break;
}
}
#else
struct comp : public binary_function<const double, const Foo&, bool> {
bool operator () (const double lhs, const Foo& rhs) { return lhs < rhs.a; }
};
cout << upper_bound(test.begin(), test.end(), 2, comp())->b << endl;
#endif
}
A couple notes here:
#if
which means the if
-block will only execute if _HAS_ITERATOR_DEBUGGING
is defined and is non-0. At design time Visual Studio 2008 seems to always think that it is undefinedcomp
inline if your particular situation requires comp
to by used in multiple places 1st consider wrapping this entire else
-block in a function to limit the number of #define
s in your code, obviously the applicability of this comment will be limited if you're using comp
in multiple standard algorithms