I guess I’ve found a G++ bug but I’m not sure. I cannot explain it. The compile shouldn’t pass BAD code but it does. g++-4.5 and g++4.6 -std=c++0x pass this code without any warning.
As is the compile thinks that pointer to Bar object is Bar object itself.
I’m crazy. I spent many hours to get the bug. Is there any technique to protect from this kind of bug?
Bad code gives:
g++-4.6 for_stackoverflow.cpp && ./a.out
address of bar in main() 0xbff18fc0
Foo 0x9e80008 Bar 0xbff18fec
Foo 0x9e80028 Bar 0xbff18fec
Foo 0x9e80048 Bar 0xbff18fec
end
Source code:
#include <iostream>
#include <list>
#include <iomanip>
#include <algorithm>
#define BAD
using namespace std;
class Bar;
class Foo {
public:
virtual void tick(Bar & b) {
cout << "Foo " << this << " Bar " << setw(14) << (&b) << endl;
}
};
class Bar : public list<Foo*> {
};
int main() {
Bar bar;
cout << "address of bar in main() " << &bar << endl;
bar.push_back(new Foo());
bar.push_back(new Foo());
bar.push_back(new Foo());
#ifdef GOOD
for_each(bar.begin(), bar.end(), bind2nd(mem_fun(&Foo::tick), bar));
#elif defined(BAD)
for_each(bar.begin(), bar.end(), bind2nd(mem_fun(&Foo::tick), &bar));
#else
#error "define GOOD xor BAD"
#endif
cout << "end" << endl;
return 0;
}
bind2ndis declared as:This means that the type
Tis deduced, in this case asBar *.On my system it’s implemented as:
To see why that would compile consider:
which seems to be the real problem and does compile with g++, because it’s basically a
reinterpret_cast.The simplest workaround is changing it to use
boost::bind(orstd::bindfor C++11):…
or a lambda function does give the error you’d expect to see.