using STL set with objects

C

CQ

Hi there,

I am having the following problem: I have the following class:

class reachGraphState {

protected:
/* ... some stuff .... */

public:
reachGraphState(stateType, bool);
reachGraphState(stateType, bool, State *);
~reachGraphState();

State * state;

static bool sortReachGraphState(const reachGraphState& left, const
reachGraphState& right) {
left.state < right.state;
}

friend bool operator == (const reachGraphState& s1, const
reachGraphState& s2);
friend bool operator < (const reachGraphState& s1, const
reachGraphState& s2);

friend ostream& operator << (std::eek:stream& os, const
reachGraphState& s);
};

And then I have another class, which shall contain a set of those
reachGraphState-objects. So I did the following:


class stateList {

private:
/* some stuff */

public:
stateList();
~stateList();

set<reachGraphState *, reachGraphState::sortReachGraphState>
myStateSet;
};


But this does not work. Can anyone help me on this. How do I declare an
STL set over objects using a certain sorting function.


Thanks a lot in advance,

CQ.
 
H

Heinz Ozwirk

CQ said:
Hi there,

I am having the following problem: I have the following class:

class reachGraphState {
/* ... some stuff .... */

State * state;

static bool sortReachGraphState(const reachGraphState& left, const
reachGraphState& right) {
left.state < right.state;
}
};

And then I have another class, which shall contain a set of those
reachGraphState-objects. So I did the following:


class stateList {
private:
/* some stuff */

set<reachGraphState *, reachGraphState::sortReachGraphState>
myStateSet;
};


But this does not work. Can anyone help me on this. How do I declare an
STL set over objects using a certain sorting function.

1. The sorting function for a set must accept two arguments of the set's
value type, either by value or by reference. Since your set's value type is
pointer to reachGraphState, you need a sorting function with two (references
to) pointers to reachGrapState, but the function you specified expects
references to reachGraphState objects, not pointers to such objects. You
didn't tell us what didn't work, but I assume you got some error message
from your compiler.

2. The sortReachGraphState function looks quite suspicious. Do you really
want to sort instances of reachClassState by the memory address of one of
their member?

Heinz
 
C

CQ

I get the following error message:

error: type/value mismatch at argument 2 in template parameter list
for `template<class _Key, class _Compare, class _Alloc> class std::set'

Yes, I want to sort by the memory address of the member "state".

Could you give me an example of how the sorting function should look
like. What parameters do I have to pass?


Thanks a lot,

CQ.
 
H

Heinz Ozwirk

CQ said:
I get the following error message:

error: type/value mismatch at argument 2 in template parameter list
for `template<class _Key, class _Compare, class _Alloc> class std::set'

Yes, I want to sort by the memory address of the member "state".

Could you give me an example of how the sorting function should look
like. What parameters do I have to pass?

The parameters of the compare function of a set should have the same type as
the elements in the set. If you have a set of reachGraphState's, you need a
function that compares two reachGraphState's, and if you have a set of
pointers to reachGraphState's you need a function that compares such
pointers:

bool less(reachGraphState const* lhs, reachGraphState const* rhs)
{
return reachGraphState::sortReachGraphState(*lhs, *rhs);
}

std::map<reachGraphState*, less> myMap;

HTH
Heinz
 
K

Kai-Uwe Bux

Heinz said:
The parameters of the compare function of a set should have the same type
as the elements in the set. If you have a set of reachGraphState's, you
need a function that compares two reachGraphState's, and if you have a set
of pointers to reachGraphState's you need a function that compares such
pointers:

bool less(reachGraphState const* lhs, reachGraphState const* rhs)
{
return reachGraphState::sortReachGraphState(*lhs, *rhs);
}

std::map<reachGraphState*, less> myMap;

That should not compile: the map<> and set<> templates expect to see a
typename where you passed a function. Try something like this instead:

#include <set>

class Object {};

struct Object_Compare {

bool operator() ( Object const &, Object const & ) {
return ( false );
}

}; // Object_Compare

int main ( void ) {
std::set< Object, Object_Compare > my_set;
}

Here Object_Compare is a default constructible class whose default
constructor yields a function object that will do the right thing.



Best

Kai-Uwe Bux
 
A

Axter

CQ said:
Hi there,

I am having the following problem: I have the following class:

class reachGraphState {

protected:
/* ... some stuff .... */

public:
reachGraphState(stateType, bool);
reachGraphState(stateType, bool, State *);
~reachGraphState();

State * state;

static bool sortReachGraphState(const reachGraphState& left, const
reachGraphState& right) {
left.state < right.state;
}

friend bool operator == (const reachGraphState& s1, const
reachGraphState& s2);
friend bool operator < (const reachGraphState& s1, const
reachGraphState& s2);

friend ostream& operator << (std::eek:stream& os, const
reachGraphState& s);
};

And then I have another class, which shall contain a set of those
reachGraphState-objects. So I did the following:


class stateList {

private:
/* some stuff */

public:
stateList();
~stateList();

set<reachGraphState *, reachGraphState::sortReachGraphState>
myStateSet;
};

Consider using a smart pointer that has value semantics for the
comparison operator.
See following smart pointers:
http://code.axter.com/copy_ptr.h
http://code.axter.com/cow_ptr.h
http://code.axter.com/smart_ptr.h

Also check out the boost weak_ptr
 
C

CQ

@ Kai-Uwe Bux

I tried your code. Now it compiles. But as I run the program I get a
segmentation as the second element gets inserted into the set.

Do you have an idea why that happens?


CQ
 
B

Ben Pope

CQ said:
@ Kai-Uwe Bux

I tried your code. Now it compiles. But as I run the program I get a
segmentation as the second element gets inserted into the set.

Do you have an idea why that happens?

Because you have misused it?

Show compilable code that demonstrates the problem.

Ben Pope
 
K

Kai-Uwe Bux

C

CQ

Okay. Here is my code:

class reachGraphState {

protected:
/* ... some stuff .... */

public:
reachGraphState(stateType, bool);
reachGraphState(stateType, bool, State *);
~reachGraphState();

State * state;

static bool sortReachGraphState(const reachGraphState& left,
const
reachGraphState& right) {
left.state < right.state;
}

friend bool operator == (const reachGraphState& s1, const
reachGraphState& s2);
friend bool operator < (const reachGraphState& s1, const
reachGraphState& s2);

friend ostream& operator << (std::eek:stream& os, const
reachGraphState& s);

};


struct Object_Compare {

bool operator() ( reachGraphState const * left, reachGraphState const
* right) {
cerr << "operator () is called " << endl;
return ( true );
}



class stateList {

private:
/* some stuff */

public:
stateList();
~stateList();

std::set<reachGraphState*, Object_Compare> mySet;


void addElement(State *, stateType, bool);

};


void stateList::addElement(State * s, stateType _type, bool isMinimal)
{

reachGraphState *state = new reachGraphState(_type, isMinimal, s);
mySet.insert(state);

cerr << mySet.size() << endl;
}

Here is the error backtrace:

(gdb) frame 0
#0 0xb7ee0f43 in std::_Rb_tree_decrement () from
/usr/lib/libstdc++.so.6
(gdb) frame 3
#3 0x08055e3e in std::set<reachGraphState*, Object_Compare,
std::allocator<reachGraphState*> >::insert (this=0x807319c,
__x=@0xbfc91bc8) at stl_set.h:314
/usr/include/c++/3.4/bits/stl_set.h:314:11369:beg:0x8055e3e
(gdb) frame 0
#0 0xb7ee0f43 in std::_Rb_tree_decrement () from
/usr/lib/libstdc++.so.6


Thanks a lot!

CQ.
 
B

Ben Pope

CQ said:
Okay. Here is my code:

class reachGraphState {

protected:
/* ... some stuff .... */

public:
reachGraphState(stateType, bool);

//stateType not declared
reachGraphState(stateType, bool, State *);

// State not declared
~reachGraphState();

State * state;

static bool sortReachGraphState(const reachGraphState& left,
const
reachGraphState& right) {
left.state < right.state;
}

friend bool operator == (const reachGraphState& s1, const
reachGraphState& s2);
friend bool operator < (const reachGraphState& s1, const
reachGraphState& s2);

friend ostream& operator << (std::eek:stream& os, const

//ostream not declered.
reachGraphState& s);

};


struct Object_Compare {

bool operator() ( reachGraphState const * left, reachGraphState const
* right) {
cerr << "operator () is called " << endl;
return ( true );
}
class stateList {

private:
/* some stuff */

public:
stateList();
~stateList();

std::set<reachGraphState*, Object_Compare> mySet;


void addElement(State *, stateType, bool);

};


void stateList::addElement(State * s, stateType _type, bool isMinimal)
{

reachGraphState *state = new reachGraphState(_type, isMinimal, s);
mySet.insert(state);

cerr << mySet.size() << endl;
}


reachGraphState not defined.

main not defined.



This is not your code, or you're not trying.

I can't help you.

Ben Pope
 
K

Kai-Uwe Bux

CQ said:
Okay. Here is my code:

No, it isn't. What you posted does not compile, not even remotely.

Again: read http://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.8

class reachGraphState {

protected:
/* ... some stuff .... */

public:
reachGraphState(stateType, bool);

my compiler complains that it does not know about stateType.
reachGraphState(stateType, bool, State *);
~reachGraphState();

State * state;

my compiler also wants to know about State.

static bool sortReachGraphState(const reachGraphState& left,
const
reachGraphState& right) {
left.state < right.state;
}

friend bool operator == (const reachGraphState& s1, const
reachGraphState& s2);
friend bool operator < (const reachGraphState& s1, const
reachGraphState& s2);

friend ostream& operator << (std::eek:stream& os, const
reachGraphState& s);

};


struct Object_Compare {

bool operator() ( reachGraphState const * left, reachGraphState const
* right) {
cerr << "operator () is called " << endl;
return ( true );

Do you mean:

return( *left < *right );
}

missing:

};



class stateList {

private:
/* some stuff */

public:
stateList();
~stateList();

std::set<reachGraphState*, Object_Compare> mySet;


void addElement(State *, stateType, bool);

};


void stateList::addElement(State * s, stateType _type, bool isMinimal)
{

reachGraphState *state = new reachGraphState(_type, isMinimal, s);
mySet.insert(state);

cerr << mySet.size() << endl;
}

Here is the error backtrace:

(gdb) frame 0
#0 0xb7ee0f43 in std::_Rb_tree_decrement () from
/usr/lib/libstdc++.so.6
(gdb) frame 3
#3 0x08055e3e in std::set<reachGraphState*, Object_Compare,
std::allocator<reachGraphState*> >::insert (this=0x807319c,
__x=@0xbfc91bc8) at stl_set.h:314
/usr/include/c++/3.4/bits/stl_set.h:314:11369:beg:0x8055e3e
(gdb) frame 0
#0 0xb7ee0f43 in std::_Rb_tree_decrement () from
/usr/lib/libstdc++.so.6

Since your code does not even have main(), there is no way for anybody to
reproduce your error. An error you cannot reproduce is hard to debug. Help
us to help you. Provide actual code.

As an off chance guess: maybe some of your numerous pointers are invalid.
Which reason do you have to believe that the error is caused by improper
handling of the set? It is quite possible that a remote bug just manifests
itself on this occasion.

Best

Kai-Uwe Bux
 
C

CQ

Thank you all so far! I deleted some of my code and now it works!!!

In the future I will post all the code so that it can be compiled. I am
sorry about that!


CQ.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top