struct A 
{
    // ...
    B* operator&();
    operator B() const;
};

__gnu_cxx::hash_set<A> stores values of B, the return type of operator&(). It 
should store values of A as the similar hash_map<A,bool> does.

The following example shows the effect. hash_set doesn't use copy constructor 
of A, instead it calls A::operator int(). When retrieving values, the iterator 
pretends to deliver A, but in real it delivers int. A::print() doesn't print 
the values _a2=1000 and 2000.

Nevertheless hash_set::value_type seems to be A (not int).



#include <ext/hash_set>
#include <ext/hash_map>
#include <iostream>

using namespace std;
using namespace __gnu_cxx;

#define WITH_SET_ERROR



struct A
{
    A( int a, int a2 )
    : 
        _a(a)
        , _a2(a2)    
    { 
        cout << "A(" << _a << ")\n"; 
    }


    A( const A& a )
    : 
        _a(a._a), 
        _a2(a._a2) 
    { 
        cout << "A(" << _a << ") copy\n"; 
    }


    ~A()
    { 
        cout << "~A(" << _a << ")\n"; 
    }



    void print() const
    { 
        cout << _a << "," << _a2; 
    }


    bool operator==( const A& a ) const
    { 
        return _a == a._a  &&  _a2 == a._a2; 
    }


#ifdef WITH_SET_ERROR
    int* operator&()
    { 
        cout << "operator &() " << _a << "\n"; return &_a; 
    }
#endif

    operator int() const
    { 
        cout << "operator int() " << _a << "\n"; 
        return _a; 
    }


    int _a;
    int _a2;
};


namespace __gnu_cxx
{
    template<>
    struct hash< A >
    {
        size_t operator() ( const A& a ) const  { return a._a; }
    };
}



int main( int, char** )
{
    A a ( 1, 1000 );
    A b ( 2, 2000 );

    cout << "a="; a.print(); cout << "\n";
    cout << "b="; b.print(); cout << "\n";
  
    {
        cout << "\nset:\n";
        typedef hash_set<A> Set;
        Set set;
        set.insert( a );
        set.insert( b );

        for( Set::iterator it = set.begin(); it != set.end(); it++ )
        {
            it->print();  cout << "\n";
        }
    }

    {
        cout << "\nmap:\n";  // hash_map is ok
        typedef hash_map<A,bool> Map;
        Map map;
        map[ a ] = true;
        map[ b ] = true;

        for( Map::iterator it = map.begin(); it != map.end(); it++ )
        {
            it->first.print();  cout << "\n";
        }
    }

    cout << "\n";
}

-- 
           Summary: __gnu_cxx::hash_set<A> uses return type of
                    A::operator&() instead of A
           Product: gcc
           Version: 3.4.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: j at zsch dot de
                CC: gcc-bugs at gcc dot gnu dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18053

Reply via email to