I’m trying to use a std::set where I will throw a bunch of edges in, and have only the unique ones remain.
An Edge is a line between two (integer indexed) nodes. Edge (1,2)==(2,1), because these edges are undirected.
I’m encountering a puzzling situation though, with this. At the section marked //?? in the code below, the behavior is not as I expect.
The results of running this code are to only keep 2 edges, (1,2) and (4,8). (2,1) is discarded by the set, but it should not be unless I activate the commented out //|| ( A==o.B && B==o.A ) section in operator==! What is happening here?
This set<Edge> implementation is leaving me feeling .. edgy.
#include <stdio.h>
#include <set>
using namespace std ;
struct Edge
{
int A,B ;
Edge( int iA, int iB ) : A(iA), B(iB) {}
bool operator==( const Edge & o ) const {
//??
return ( A==o.A && B==o.B ) ;//|| ( A==o.B && B==o.A ) ;
}
bool operator<( const Edge& o ) const {//MUST BE CONST
return A < o.A && B < o.B ;
}
void print() const { printf( "( %d, %d )", A,B ) ; }
void compare( const Edge& o ) const {
print() ;
if( *this==o ) printf( "==" ) ;
else printf( "!=" ) ;
o.print() ;
puts("");
}
} ;
int main()
{
Edge e1( 1, 2 ) ;
Edge e2( 1, 2 ) ;
Edge e3( 2, 1 ) ;
Edge e4( 4, 8 ) ;
e1.compare( e2 ) ;
e1.compare( e3 ) ;
e1.compare( e4 ) ;
set<Edge> edges ;
edges.insert( e1 ) ;
edges.insert( e2 ) ;
edges.insert( e3 ) ;
edges.insert( e4 ) ;
printf( "%d edges\n", edges.size() ) ;
for( auto edge : edges )
{
edge.print();
}
}
I suggest that you change your Edge() constructor to ensure that A and B are always initialized such that
A<=B(if edges can point back to their originating node) orA<B(if not), and forego having the extra logic in the operator== implementation. That seems less “edgy” to me.