http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51538
--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> 2011-12-14 01:53:00 UTC --- (In reply to comment #0) > Here source exaple: > ////////////////////////////////////////////////// > > #include <set> > #include <cstdlib> > #include <cstdio> > #include <cstdlib> You're missing <string.h> and "using namespace std;" > typedef char FOO[8]; > > void randomFOO(FOO * uidl) > { > for(int i = 0; i < sizeof(uidl); ++i) Why sizeof(uidl) not sizeof(*uidl)? > { > unsigned char byte = rand() * 256 / RAND_MAX; When RAND_MAX == INT_MAX this calculation will either overflow (causing undefined behaviour) or will produce zero. That's probably not what you want. maybe you want: unsigned char byte = rand() * 256. / RAND_MAX; > *((char*)uidl + i) = byte; > } > } > > struct FOOwrapper > { > FOOwrapper(const FOO * uidl) > { > memcpy(&m_uidl, uidl, sizeof(FOO)); > } > FOOwrapper(const FOOwrapper & othr) > { > memcpy(&m_uidl, &othr.m_uidl, sizeof(FOO)); > } This copy constructor is unnecessary, the implicit one would do the same thing. > const FOOwrapper & operator=(const FOOwrapper & othr) > { > memcpy(&m_uidl, &othr.m_uidl, sizeof(FOO)); > return *this; > } This assignment operator is unnecessary, the implicit one would do the same thing. > bool operator<(const FOOwrapper & othr) const > { > return memcmp(&m_uidl, &othr.m_uidl, sizeof(FOO)); This is not anti-symmetric so is not suitable for comparing elements of a std::set, try this: FOO f1 = { 1 }; FOO f2 = { 2 }; FOOwrapper w1(&f1); FOOwrapper w2(&f2); if (w1 < w2) assert( !(w2 < w1) ); Your operator says that x is less than y and also y is less than x. You probably want: return memcmp(&m_uidl, &othr.m_uidl, sizeof(FOO)) < 0; > } > > FOO m_uidl; > }; > > std::set<FOOwrapper> fooset; > > static const int size = 5; > > //#define SIMPLE_INSERT > > int main(int argc, char *argv[]) > { > FOOwrapper * wrap = static_cast<FOOwrapper > *>(malloc(size*sizeof(FOOwrapper))); > for(int i = 0; i < size; ++i) > { > FOO uidl; > randomFOO(&uidl); > new (wrap + i) FOOwrapper(&uidl); > #ifdef SIMPLE_INSERT > fooset.insert(wrap[i]); > #endif > } > #ifndef SIMPLE_INSERT > fooset.insert(wrap, wrap + size); > #endif > printf("size: %d\n\n", fooset.size()); > > std::set<FOOwrapper>::const_iterator it = fooset.begin(); > for(int i = 0; it != fooset.end(); ++it,++i) > printf("%d\n", i); > free(wrap); > return 0; > } > > ////////////////////////////////////////////////// > > if SIMPLE_INSERT is not defined then output will be: > > size: <value of variable size> > > 0 > 1 > > No matter how many elements being inserted output always is the same. In other > words we are limited to iterating only trough 2 elements. > > if SIMPLE_INSERT is defined, ie used std::set::insert(const value_type& x) > method, then iterating through collection is proper. I get the same result even when SIMPLE_INSERT is defined, because all FOO objects consist entirely of zeros, so you try to insert duplicates. > This source code, compiled with VSC++ 2010 works fine in both cases. The source code is totally broken. With the changes above to randomFOO and operator< it works.