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.

Reply via email to