473,407 Members | 2,629 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,407 software developers and data experts.

Is this a valid less than operator for a map?

I have a class that already has == and != operators that I want to use
in a map that uses my class (not a pointer to the class) as the key.
To do this I need a < operator. Is this a valid less than operator to
use in this case?
bool MyClass::operator<(const MyClass &other) const
{
if (*this == other) return false;
return (this < &other);
}

I can declare and use a map variable using this operator

std::map<MyClass,std::string> m_MyClassCache;

I am worried that if the map is sorted and then something is added and
the map is reallocated by copying to a new array the previosly sorted
items may no longer be sorted. Is this likely to be a problem?

Thanks
Aug 22 '08 #1
12 5726
On 22 Aug., 12:51, "dimsttho...@yahoo.com" <dimsttho...@yahoo.com>
wrote:
I have a class that already has == and != operators that I want to use
in a map that uses my class (not a pointer to the class) as the key.
To do this I need a < operator. Is this a valid less than operator to
use in this case?

bool MyClass::operator<(const MyClass &other) const
{
* * * * if (*this == other) return false;
* * * * return (this < &other);

}
No - it is not valid. Swapping the elements around will change the
predicate so that you for two elements could have a < b and b < a at
different times.

/Peter
Aug 22 '08 #2
Hi,

Your key to the map sorts on the memory address i.e. pointer to it (usually
this is not what you want). Here is a key from a map i.e. the map[ Key ] =
Data; (The map only needs the < operator).
Example:

class MMyClass
{
private:
std::string Key1; // Part one of the key
std::string Key2; // Part two of the key
std::string Key3; // Part three of the key

public:
MMyClass( const std::string& Key1, const std::string& Key2, const
std::string& Key3):
Key1( Key1 ),
Key2( Key2 ),
Key3( Key3 )
{
}
bool operator<( const MMyClass& MyClass ) const
{
if( Key1 < MyClass.Key1 ) return true;
else if( Key1 == MyClass.Key1 )
{
if( Key2 < MyClass.Key2 ) return true;
else if( Key2 == MyClass.Key2 )
{
return Key3 < MyClass.Key3;
}
}

return false;
}
};


Regards, Ron AF Greve

http://www.InformationSuperHighway.eu

<di*********@yahoo.comwrote in message
news:eb**********************************@y21g2000 hsf.googlegroups.com...
>I have a class that already has == and != operators that I want to use
in a map that uses my class (not a pointer to the class) as the key.
To do this I need a < operator. Is this a valid less than operator to
use in this case?
bool MyClass::operator<(const MyClass &other) const
{
if (*this == other) return false;
return (this < &other);
}

I can declare and use a map variable using this operator

std::map<MyClass,std::stringm_MyClassCache;

I am worried that if the map is sorted and then something is added and
the map is reallocated by copying to a new array the previosly sorted
items may no longer be sorted. Is this likely to be a problem?

Thanks

Aug 22 '08 #3
On 22 Aug, 12:18, peter koch <peter.koch.lar...@gmail.comwrote:
On 22 Aug., 12:51, "dimsttho...@yahoo.com" <dimsttho...@yahoo.com>
wrote:
I have a class that already has == and != operators that I want to use
in a map that uses my class (not a pointer to the class) as the key.
To do this I need a < operator. Is this a valid less than operator to
use in this case?
bool MyClass::operator<(const MyClass &other) const
{
* * * * if (*this == other) return false;
* * * * return (this < &other);
}

No - it is not valid. Swapping the elements around will change the
predicate so that you for two elements could have a < b and b < a at
different times.
I thought it was a bit dodgy. I have come up with a better solution
using an instance variable (which is not compared in the == operator):

class MyClass
{
...

private:
unsigned long m_instance;
static unsigned long m_instanceCount;
};

unsigned long MyClass::m_instanceCount = 0;

MyClass::MyClass() : m_instance(m_instanceCount++)
{
}

MyClass::MyClass(double x, double y) : m_instance(m_instanceCount++)
{
}

MyClass::MyClass(const MyClass& rhs) : m_instance(rhs.m_instance)
{
}

MyClass& MyClass::operator=(const MyClass& rhs)
{
if (this != &rhs)
{
...
m_instance = rhs.m_instance;
}
return *this;
}

bool MyClass::operator<(const MyClass &other) const
{
if (*this == other) return false;
return (m_instance < other.m_instance);
}

Aug 22 '08 #4
On 22 Aug, 12:37, "Ron AF Greve" <ron@localhostwrote:
Hi,

Your key to the map sorts on the memory address i.e. pointer to it (usually
this is not what you want). Here is a key from a map i.e. the map[ Key ] =
Data; (The map only needs the < operator).
Example:

class MMyClass
{
* private:
* * std::string Key1; // Part one of the key
* * std::string Key2; // Part two of the key
* * std::string Key3; // Part three of the key

* public:
* * MMyClass( *const std::string& Key1, const std::string& Key2, const
std::string& Key3):
* * * Key1( Key1 ),
* * * Key2( Key2 ),
* * * Key3( Key3 )
* * {
* * }
* * bool operator<( const MMyClass& MyClass ) const
* * {
* * * if( Key1 < MyClass.Key1 ) return true;
* * * else if( Key1 == MyClass.Key1 )
* * * {
* * * * if( Key2 < MyClass.Key2 ) return true;
* * * * else if( Key2 == MyClass.Key2 )
* * * * {
* * * * * return Key3 < MyClass.Key3;
* * * * }
* * * }

* * * return false;
* * }

};

Regards, Ron AF Greve

Yes, but the problem is the class I am using has a lot of member data
and already has an == operator and I wanted to avoid having to write a
fully fledged < operator. See my other reply.

Aug 22 '08 #5
On 22 Aug, 12:41, "dimsttho...@yahoo.com" <dimsttho...@yahoo.com>
wrote:
On 22 Aug, 12:18, peter koch <peter.koch.lar...@gmail.comwrote:


On 22 Aug., 12:51, "dimsttho...@yahoo.com" <dimsttho...@yahoo.com>
wrote:
I have a class that already has == and != operators that I wantto use
in a map that uses my class (not a pointer to the class) as the key.
To do this I need a < operator. Is this a valid less than operator to
use in this case?
bool MyClass::operator<(const MyClass &other) const
{
* * * * if (*this == other) return false;
* * * * return (this < &other);
}
No - it is not valid. Swapping the elements around will change the
predicate so that you for two elements could have a < b and b < a at
different times.

I thought it was a bit dodgy. I have come up with a better solution
using an instance variable (which is not compared in the == operator):

class MyClass
{
...

private:
* * * * unsigned long m_instance;
* * * * static unsigned long m_instanceCount;

};

unsigned long MyClass::m_instanceCount = 0;

MyClass::MyClass() : m_instance(m_instanceCount++)
{

}

MyClass::MyClass(double x, double y) : m_instance(m_instanceCount++)
{

}

MyClass::MyClass(const MyClass& rhs) : m_instance(rhs.m_instance)
{

}

MyClass& MyClass::operator=(const MyClass& rhs)
{
* * * * if (this != &rhs)
* * * * {
* * * * * * * * ...
* * * * * * * * m_instance * *= rhs.m_instance;
* * * * }
* * * * return *this;

}

bool MyClass::operator<(const MyClass &other) const
{
* * * * if (*this == other) return false;
* * * * return (m_instance < other.m_instance);

}- Hide quoted text -

- Show quoted text -- Hide quoted text -

- Show quoted text -
This solution doesn't work either as the map doesn't compare every
item when inserting new items, I assume it does some kind of binary
search based on the sorted list (which is the whole point of a map!).
Looks like I will have to implement a proper less than operator.
Aug 22 '08 #6
di*********@yahoo.com wrote:
On 22 Aug, 12:41, "dimsttho...@yahoo.com" <dimsttho...@yahoo.com>
wrote:
>On 22 Aug, 12:18, peter koch <peter.koch.lar...@gmail.comwrote:


>>On 22 Aug., 12:51, "dimsttho...@yahoo.com" <dimsttho...@yahoo.com>
wrote:
I have a class that already has == and != operators that I want to use
in a map that uses my class (not a pointer to the class) as the key.
To do this I need a < operator. Is this a valid less than operator to
use in this case?
bool MyClass::operator<(const MyClass &other) const
{
if (*this == other) return false;
return (this < &other);
}
No - it is not valid. Swapping the elements around will change the
predicate so that you for two elements could have a < b and b < a at
different times.
I thought it was a bit dodgy. I have come up with a better solution
using an instance variable (which is not compared in the == operator):

class MyClass
{
...

private:
unsigned long m_instance;
static unsigned long m_instanceCount;

};

unsigned long MyClass::m_instanceCount = 0;

MyClass::MyClass() : m_instance(m_instanceCount++)
{

}

MyClass::MyClass(double x, double y) : m_instance(m_instanceCount++)
{

}

MyClass::MyClass(const MyClass& rhs) : m_instance(rhs.m_instance)
{

}

MyClass& MyClass::operator=(const MyClass& rhs)
{
if (this != &rhs)
Remove the above line with if
> {
...
m_instance = rhs.m_instance;
}
return *this;

}

bool MyClass::operator<(const MyClass &other) const
{
if (*this == other) return false;
Remove the above line with if
> return (m_instance < other.m_instance);


This solution doesn't work either as the map doesn't compare every
item when inserting new items, I assume it does some kind of binary
search based on the sorted list (which is the whole point of a map!).
Looks like I will have to implement a proper less than operator.

Why it doesn't work? It should work
Do you have a compilable example?
Aug 22 '08 #7
Hi,

It is a lot of work :-(. Since I often access databases I actually got tired
of writing a key class everytime so I sort of created a simple javascript
that does some of the work. (It is just a quick script and not bugfree but
does the job for me, currently only supports strings though).

http://informationsuperhighway.eu/genkey.html
Regards, Ron AF Greve

http://www.InformationSuperHighway.eu

<di*********@yahoo.comwrote in message
news:de**********************************@a1g2000h sb.googlegroups.com...
On 22 Aug, 12:37, "Ron AF Greve" <ron@localhostwrote:
Hi,

Your key to the map sorts on the memory address i.e. pointer to it
(usually
this is not what you want). Here is a key from a map i.e. the map[ Key ] =
Data; (The map only needs the < operator).
Example:

class MMyClass
{
private:
std::string Key1; // Part one of the key
std::string Key2; // Part two of the key
std::string Key3; // Part three of the key

public:
MMyClass( const std::string& Key1, const std::string& Key2, const
std::string& Key3):
Key1( Key1 ),
Key2( Key2 ),
Key3( Key3 )
{
}
bool operator<( const MMyClass& MyClass ) const
{
if( Key1 < MyClass.Key1 ) return true;
else if( Key1 == MyClass.Key1 )
{
if( Key2 < MyClass.Key2 ) return true;
else if( Key2 == MyClass.Key2 )
{
return Key3 < MyClass.Key3;
}
}

return false;
}

};

Regards, Ron AF Greve

Yes, but the problem is the class I am using has a lot of member data
and already has an == operator and I wanted to avoid having to write a
fully fledged < operator. See my other reply.
Aug 22 '08 #8
On Aug 22, 4:18*am, peter koch <peter.koch.lar...@gmail.comwrote:
On 22 Aug., 12:51, "dimsttho...@yahoo.com" <dimsttho...@yahoo.com>
wrote:
I have a class that already has == and != operators that I want to use
in a map that uses my class (not a pointer to the class) as the key.
To do this I need a < operator. Is this a valid less than operator to
use in this case?
bool MyClass::operator<(const MyClass &other) const
{
* * * * if (*this == other) return false;
* * * * return (this < &other);
}

No - it is not valid. Swapping the elements around will change the
predicate so that you for two elements could have a < b and b < a at
different times.
I don't see why this operator<() would be invalid - that is, why it
would not produce a total ordering of MyClass elements. After all,
swapping the left and right elements would effectively also swap the
values of "other" and "this". And presumably whenever

this < &other

is true than

&other < this

will be false. Just as, whenever:

other == *this

is true, then

*this == other

is certain to be true as well.

Admittedly the operator<() here doesn't seem to have any practical
value. Nevertheless it does appear to me - to be valid.

Greg

Aug 22 '08 #9
On 2008-08-22 08:13:31 -0400, "di*********@yahoo.com"
<di*********@yahoo.comsaid:
>
This solution doesn't work either as the map doesn't compare every
item when inserting new items, I assume it does some kind of binary
search based on the sorted list (which is the whole point of a map!).
Looks like I will have to implement a proper less than operator.
Good idea. If you have to fight with the design, chances are you're
doing something wrong.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Aug 22 '08 #10
[huge snip]
This might help you solve the problem:
http://www.parashift.com/c++-faq-lit...t.html#faq-5.8
Aug 22 '08 #11
On 22 Aug., 14:49, Greg Herlihy <gre...@mac.comwrote:
On Aug 22, 4:18*am, peter koch <peter.koch.lar...@gmail.comwrote:


On 22 Aug., 12:51, "dimsttho...@yahoo.com" <dimsttho...@yahoo.com>
wrote:
I have a class that already has == and != operators that I wantto use
in a map that uses my class (not a pointer to the class) as the key.
To do this I need a < operator. Is this a valid less than operator to
use in this case?
bool MyClass::operator<(const MyClass &other) const
{
* * * * if (*this == other) return false;
* * * * return (this < &other);
}
No - it is not valid. Swapping the elements around will change the
predicate so that you for two elements could have a < b and b < a at
different times.

I don't see why this operator<() would be invalid - that is, why it
would not produce a total ordering of MyClass elements. After all,
swapping the left and right elements would effectively also swap the
values of "other" and "this". And presumably whenever

* * *this < &other

is true than

* * &other < this

will be false. Just as, whenever:

* * other == *this

is true, then

* * *this == other

is certain to be true as well.

Admittedly the operator<() here doesn't seem to have any practical
value. Nevertheless it does appear to me - to be valid.

Greg
I had the same initial thought as you: I do not remember this being
implicitly forbidden in the standard, but then I have not studied the
standard that much.
However, the problem is that the compares are not related to the
object but to some transient property of it.
When the object is to be inserted into the map, the address of the
object to be inserted will be used, but the moment the object is
inserted, the property changes.
The consequence is of course that this never is going to work: we will
get a map that is not sorted (or a crash), just as if we did apply a
comparison function that is not sanctioned by the standard.

/Peter
Aug 23 '08 #12
On Aug 22, 3:46 pm, "dimsttho...@yahoo.com" <dimsttho...@yahoo.com>
wrote:
On 22 Aug, 12:37, "Ron AF Greve" <ron@localhostwrote:
Hi,
Your key to the map sorts on the memory address i.e. pointer to it (usually
this is not what you want). Here is a key from a map i.e. the map[ Key ] =
Data; (The map only needs the < operator).
Example:
class MMyClass
{
private:
std::string Key1; // Part one of the key
std::string Key2; // Part two of the key
std::string Key3; // Part three of the key
public:
MMyClass( const std::string& Key1, const std::string& Key2, const
std::string& Key3):
Key1( Key1 ),
Key2( Key2 ),
Key3( Key3 )
{
}
bool operator<( const MMyClass& MyClass ) const
{
if( Key1 < MyClass.Key1 ) return true;
else if( Key1 == MyClass.Key1 )
{
if( Key2 < MyClass.Key2 ) return true;
else if( Key2 == MyClass.Key2 )
{
return Key3 < MyClass.Key3;
}
}
return false;
}
};
Regards, Ron AF Greve

Yes, but the problem is the class I am using has a lot of member data
and already has an == operator and I wanted to avoid having to write a
fully fledged < operator. See my other reply.

normally equality(==) operator is not intended to have the **ordering
property** and **you have to declare at least one ordering function in
case of need for sorting**.So do not be lazy to define at least one of
the operators < , =< , =,from each you can build the other three
and equality.
consider the complex numbers; mathematically you can test two complex
numbers against identity but there exists no formal ordering for
complex numbers exept personal interpretations.

regards,
FM.
Aug 23 '08 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: news | last post by:
I have lines of code that look like this: while ($row2sx = mysql_fetch_array($result2sx)) { Now that's the way I've always learned to create an array from a mySQL querey. I just started...
6
by: Dave Theese | last post by:
Please see questions in the code below... Thanks! #include <iostream> using namespace std; class foo_class { public: foo_class() {cout << "Constructing..." << endl;}
23
by: James Aguilar | last post by:
Someone showed me something today that I didn't understand. This doesn't seem like it should be valid C++. Specifically, I don't understand how the commas are accepted after the function...
5
by: lallous | last post by:
Hello How can I define an operator for such: bool operator<(my_class *l,my_class *r) { return l->_attribute < r->_attribute; } So that I can use with std::less, as:
11
by: Martin Jørgensen | last post by:
Hi, - - - - - - - - - - - - - - - #include <iostream> #include <string> #include <map> using namespace std; int main() {
60
by: andrew queisser | last post by:
Is this code below valid C++? I'd like to use this construct but I'm not sure if it'll be portable. struct foo { char x; }; struct bar { char sameSizeAsFooX;
16
by: Cory Nelson | last post by:
Does anyone know how std::set prevents duplicates using only std::less? I've tried looking through a couple of the STL implementations and their code is pretty unreadable (to allow for different...
3
by: ek | last post by:
I have the following class: template<typename I> class test { public: test(I i) : pp(i) {} I getpp() const { return pp; }
9
by: Marijn | last post by:
Hey everybody, I was wondering if the following would be a valid JavaScript assignment vor a variable and if anybody knows this to work in IE6 or lower? var someVar = (typeof(someVar) ===...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.