Get a C++ set to contain objects

J

janzon

Hi!

I'm a Java guy, forced to do some C++. I want to add objects to the set
container. I don't even get past the compilation step (which is a good
thing in a way). For instance, why doesn't the following code compile?

#include <iostream>
#include <set>

using namespace std;

class myClass {
public:
void hello() { cout << "hello"; }
};

int main() {
myClass mc;

set<myClass> s;
s.insert(mc); // If this line is commented away, no error
}


The compiles gives as a reason the following:

bik> CC -o prog4 prog4.cc
"/opt/SUNWspro/prod/include/CC/Cstd/./functional", line 166: Error: The
operation "const myClass<const myClass" is illegal.
"/opt/SUNWspro/prod/include/CC/Cstd/rw/tree.cc", line 177: Where:
While instantiating "std::less<myClass>::eek:perator()(const myClass&,
const myClass&) const".
"/opt/SUNWspro/prod/include/CC/Cstd/rw/tree.cc", line 177: Where:
Instantiated from __rwstd::__rb_tree<myClass, myClass,
__rwstd::__ident<myClass, myClass>, std::less<myClass>,
std::allocator<myClass>>::insert(const myClass&).
"/opt/SUNWspro/prod/include/CC/Cstd/./set", line 224: Where:
Instantiated from non-template code.
1 Error(s) detected.
 
K

Kai-Uwe Bux

Hi!

I'm a Java guy, forced to do some C++. I want to add objects to the set
container. I don't even get past the compilation step (which is a good
thing in a way). For instance, why doesn't the following code compile?

#include <iostream>
#include <set>

using namespace std;

class myClass {
public:
void hello() { cout << "hello"; }
};

int main() {
myClass mc;

set<myClass> s;
s.insert(mc); // If this line is commented away, no error
}
[snip]

The std::set<> container keeps its elements in order. For this to happen,
you need to supply a comparison predicate. Technically, you have the
following options:

a) Define an operator< for myClass. This can be either a member operator or
a freestanding friend. This solution conveys the message that the objects
of type myClass a naturally comparable.

b) Specialize std::less<myClass>. This indicates that the ordering you
define is less natural and more of a hack to make things like std::set and
std::map work.

c) Define a freestanding comparison function

bool some_function_name ( myClass const &, myClass const & );

and pass it as a parameter upon construction of the set. Generally, I would
not recommend this since you will have to supply additional template
parameters and it makes the code less readable. This, I would use only when
there are several sorting criteria for the same type that I need to use
independently in the code.


In any case, the comparison predicate you supply has to define a ordering,
i.e., you may not have things like a < b < c < a and you should have either
a<b or b<a or a==b. If these conditions are not met, the code is likely to
compiler but it is also likely to give unexpected results (aka bugs).


Best

Kai-Uwe Bux
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

int main() {
myClass mc;

set<myClass> s;
s.insert(mc); // If this line is commented away, no error
}

std::set is ordered, then it needs a way to compare things (and also to
evaluate equality). You need a < operator for objects of your class, or an
specialization for him of the std::less template, or add to the definition
of your set a compare operation.
 
D

Daniel T.

Hi!

I'm a Java guy, forced to do some C++. I want to add objects to the set
container. I don't even get past the compilation step (which is a good
thing in a way). For instance, why doesn't the following code compile?

#include <iostream>
#include <set>

using namespace std;

class myClass {
public:
void hello() { cout << "hello"; }
};

int main() {
myClass mc;

set<myClass> s;
s.insert(mc); // If this line is commented away, no error
}

Note, although the above compiles in Java, it wouldn't work because the
set (TreeMap in Java) has no way to compare two myClass objects to see
what the order should be.
The compiles gives as a reason the following:

bik> CC -o prog4 prog4.cc
"/opt/SUNWspro/prod/include/CC/Cstd/./functional", line 166: Error: The
operation "const myClass<const myClass" is illegal.
"/opt/SUNWspro/prod/include/CC/Cstd/rw/tree.cc", line 177: Where:
While instantiating "std::less<myClass>::eek:perator()(const myClass&,
const myClass&) const".

The above complains about the very thing that would cause this code to
fail in Java. No way to compare two myClass objects to determine order.

To do that in C++, you must provide a global function that returns true
of the left hand argument comes before the right hand argument.

bool compare( const myClass& lhs, const myClass& rhs ) {
// return true if lhs should come before rhs, otherwise return false.
}

If you name your compare function "operator<" then the set will just
work. If you want to name it something else, then you will need to let
set know.
 
L

lw1a2

Hi!

I'm a Java guy, forced to do some C++. I want to add objects to the set
container. I don't even get past the compilation step (which is a good
thing in a way). For instance, why doesn't the following code compile?

#include <iostream>
#include <set>

using namespace std;

class myClass {
public:
void hello() { cout << "hello"; }
};

int main() {
myClass mc;

set<myClass> s;
s.insert(mc); // If this line is commented away, no error
}


The compiles gives as a reason the following:

bik> CC -o prog4 prog4.cc
"/opt/SUNWspro/prod/include/CC/Cstd/./functional", line 166: Error: The
operation "const myClass<const myClass" is illegal.
"/opt/SUNWspro/prod/include/CC/Cstd/rw/tree.cc", line 177: Where:
While instantiating "std::less<myClass>::eek:perator()(const myClass&,
const myClass&) const".
"/opt/SUNWspro/prod/include/CC/Cstd/rw/tree.cc", line 177: Where:
Instantiated from __rwstd::__rb_tree<myClass, myClass,
__rwstd::__ident<myClass, myClass>, std::less<myClass>,
std::allocator<myClass>>::insert(const myClass&).
"/opt/SUNWspro/prod/include/CC/Cstd/./set", line 224: Where:
Instantiated from non-template code.
1 Error(s) detected.

You must overload myClass's operator <
Like this:

#include <iostream>
#include <set>
using namespace std;


class myClass {
public:
myClass():data(0){}
void hello() { cout << "hello"; }
bool operator<(const myClass& rhs) const
{
return data<rhs.data;
}
private:
int data;//This is a comparative data.
};


int main() {
myClass mc;

set<myClass> s;
s.insert(mc); // If this line is commented away, no error



}
 
S

Stuart Golodetz

Daniel T. said:
Note, although the above compiles in Java, it wouldn't work because the
set (TreeMap in Java) has no way to compare two myClass objects to see
what the order should be.

TreeSet surely?

<snip>
 

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

Forum statistics

Threads
473,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top