473,388 Members | 1,256 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,388 software developers and data experts.

Problems with std::less

ek
I have the following class:

template<typename I>
class test {
public:
test(I i) : pp(i) {}

I getpp() const {
return pp;
}

void setpp(I i) {
pp = i;
}

bool operator<(const test& t) const {
return (this < &t);
}
private:
I pp;
};

In main I do:

int main(){

test<intt1(1);
test<intt2(2);

std::less<test<int C;
std::cout << "C(t1,t2) = " << C(t1,t2) << std::endl;
std::cout << "C(t1,t1) = " << C(t1,t1) << std::endl;

return 0
}

But it prints 0 in both cases. How do I compare objects? When I supply
these objects to a std::set the '<' operator in my class should work
so at the moment the tree would not be balanced correctly.
Another thing. I don't see the point in using 'C' I can just use the
operator '<' directly:

std::cout << "t1 < t2 = " << (t1 < t2) << std::endl;
std::cout << "t1 < t1 = " << (t1 < t1) << std::endl;

which gives the same result, so why go through the extra layer with
using std::less which just calls the '<' anyway instead of just
calling '<' directly?

Jun 10 '07 #1
3 2260
On 2007-06-10 14:28, ek wrote:
I have the following class:

template<typename I>
class test {
public:
test(I i) : pp(i) {}

I getpp() const {
return pp;
}

void setpp(I i) {
pp = i;
}

bool operator<(const test& t) const {
return (this < &t);
}
private:
I pp;
};

In main I do:

int main(){

test<intt1(1);
test<intt2(2);

std::less<test<int C;
std::cout << "C(t1,t2) = " << C(t1,t2) << std::endl;
std::cout << "C(t1,t1) = " << C(t1,t1) << std::endl;

return 0
}

But it prints 0 in both cases. How do I compare objects? When I supply
these objects to a std::set the '<' operator in my class should work
so at the moment the tree would not be balanced correctly.
To compare two objects you have to decide what the properties that
defines the object are, and then how you based on this order objects. In
the code above you have decide that the address of the object determines
which is the smallest one. This is generally a bad idea since the result
of comparing two objects might not be the same as when two copies of
them are compared.

In your case the natural thing to compare would be the value of pp, so
change your operator < to:

bool operator<(const test& t) const {
return (pp < t.pp);
}

and you'll get the expected results when you run the program.
Another thing. I don't see the point in using 'C' I can just use the
operator '<' directly:

std::cout << "t1 < t2 = " << (t1 < t2) << std::endl;
std::cout << "t1 < t1 = " << (t1 < t1) << std::endl;

which gives the same result, so why go through the extra layer with
using std::less which just calls the '<' anyway instead of just
calling '<' directly?
The idea of using std::less in a container is that the user can specify
how they want their objects compared, if we take std::set as an example
it has the following signature (from VC++2005):

template <class Key,
class Traits=less<Key>,
class Allocator=allocator<Key>
>
class set;

So, Key is the type of object you want to store in the set, Traits tells
you how to compare two objects, and Allocator how they are allocated. As
you can see the default comparator is std::less, which means that the
objects < operator will be used, but you can change this to std::greater
to use the objects' instead, or you can create a specialized one that
compares the results of calling foo(5) on the objects.

If you add an operator like this to test:

bool operator>(const test& t) const {
return (this->pp t.pp);
}

And take a look at this code which implements a class that keeps a copy
of an object:

template<class T, class Comp>
class KeepOne
{
T theOne;
Comp C;
public:
KeepOne(T init) : theOne(init) {}
void insert(T t)
{
if (C(t, theOne))
theOne = t;
}
T& get() { return theOne; }
};

int main()
{
test<intt1(1);
test<intt2(2);

KeepOne<test<int>, std::less<test<int k(t2);
k.insert(t1);
std::cout << k.get().getpp();
}
As you can see, when you insert() into the KeepOne object it will only
keep one object and the one that it keeps is determined by the
comparator used. Replace std::less<test<int with
std::greater<test<int and you'll see that it will keep t2 instead of t1.

--
Erik Wikström
Jun 10 '07 #2
Erik Wikström wrote:
On 2007-06-10 14:28, ek wrote:
>I have the following class:

template<typename I>
class test {
public:
test(I i) : pp(i) {}

I getpp() const {
return pp;
}

void setpp(I i) {
pp = i;
}

bool operator<(const test& t) const {
return (this < &t);
}
private:
I pp;
};

In main I do:

int main(){

test<intt1(1);
test<intt2(2);

std::less<test<int C;
std::cout << "C(t1,t2) = " << C(t1,t2) << std::endl;
std::cout << "C(t1,t1) = " << C(t1,t1) << std::endl;

return 0
}

But it prints 0 in both cases. How do I compare objects? When I supply
these objects to a std::set the '<' operator in my class should work
so at the moment the tree would not be balanced correctly.

To compare two objects you have to decide what the properties that
defines the object are, and then how you based on this order objects. In
the code above you have decide that the address of the object determines
which is the smallest one. This is generally a bad idea since the result
of comparing two objects might not be the same as when two copies of
them are compared.

In your case the natural thing to compare would be the value of pp, so
change your operator < to:

bool operator<(const test& t) const {
return (pp < t.pp);
}

and you'll get the expected results when you run the program.
>Another thing. I don't see the point in using 'C' I can just use the
operator '<' directly:

std::cout << "t1 < t2 = " << (t1 < t2) << std::endl;
std::cout << "t1 < t1 = " << (t1 < t1) << std::endl;

which gives the same result, so why go through the extra layer with
using std::less which just calls the '<' anyway instead of just
calling '<' directly?

The idea of using std::less in a container is that the user can specify
how they want their objects compared, if we take std::set as an example
it has the following signature (from VC++2005):

template <class Key,
class Traits=less<Key>,
class Allocator=allocator<Key>
>
class set;

So, Key is the type of object you want to store in the set, Traits tells
you how to compare two objects, and Allocator how they are allocated. As
you can see the default comparator is std::less, which means that the
objects < operator will be used, but you can change this to std::greater
to use the objects' instead, or you can create a specialized one that
compares the results of calling foo(5) on the objects.

If you add an operator like this to test:

bool operator>(const test& t) const {
return (this->pp t.pp);
}

And take a look at this code which implements a class that keeps a copy
of an object:

template<class T, class Comp>
class KeepOne
{
T theOne;
Comp C;
public:
KeepOne(T init) : theOne(init) {}
void insert(T t)
{
if (C(t, theOne))
theOne = t;
}
T& get() { return theOne; }
};

int main()
{
test<intt1(1);
test<intt2(2);

KeepOne<test<int>, std::less<test<int k(t2);
k.insert(t1);
std::cout << k.get().getpp();
}
As you can see, when you insert() into the KeepOne object it will only
keep one object and the one that it keeps is determined by the
comparator used. Replace std::less<test<int with
std::greater<test<int and you'll see that it will keep t2 instead of
t1.
Ok but the more general idea is that the point of using a Comparator is
that you don't need to change the code in the container that uses the
comparator. As long as you implement the operators in the objects being
stored you can just change the Comparator instead of writing a copy of
the container where it uses < instead og >, right?
Jun 10 '07 #3
On 2007-06-10 20:09, desktop wrote:
Erik Wikström wrote:
>On 2007-06-10 14:28, ek wrote:
>>I have the following class:

template<typename I>
class test {
public:
test(I i) : pp(i) {}

I getpp() const {
return pp;
}

void setpp(I i) {
pp = i;
}

bool operator<(const test& t) const {
return (this < &t);
}
private:
I pp;
};

In main I do:

int main(){

test<intt1(1);
test<intt2(2);

std::less<test<int C;
std::cout << "C(t1,t2) = " << C(t1,t2) << std::endl;
std::cout << "C(t1,t1) = " << C(t1,t1) << std::endl;

return 0
}

But it prints 0 in both cases. How do I compare objects? When I supply
these objects to a std::set the '<' operator in my class should work
so at the moment the tree would not be balanced correctly.

To compare two objects you have to decide what the properties that
defines the object are, and then how you based on this order objects. In
the code above you have decide that the address of the object determines
which is the smallest one. This is generally a bad idea since the result
of comparing two objects might not be the same as when two copies of
them are compared.

In your case the natural thing to compare would be the value of pp, so
change your operator < to:

bool operator<(const test& t) const {
return (pp < t.pp);
}

and you'll get the expected results when you run the program.
>>Another thing. I don't see the point in using 'C' I can just use the
operator '<' directly:

std::cout << "t1 < t2 = " << (t1 < t2) << std::endl;
std::cout << "t1 < t1 = " << (t1 < t1) << std::endl;

which gives the same result, so why go through the extra layer with
using std::less which just calls the '<' anyway instead of just
calling '<' directly?

The idea of using std::less in a container is that the user can specify
how they want their objects compared, if we take std::set as an example
it has the following signature (from VC++2005):

template <class Key,
class Traits=less<Key>,
class Allocator=allocator<Key>
> >
class set;

So, Key is the type of object you want to store in the set, Traits tells
you how to compare two objects, and Allocator how they are allocated. As
you can see the default comparator is std::less, which means that the
objects < operator will be used, but you can change this to std::greater
to use the objects' instead, or you can create a specialized one that
compares the results of calling foo(5) on the objects.

If you add an operator like this to test:

bool operator>(const test& t) const {
return (this->pp t.pp);
}

And take a look at this code which implements a class that keeps a copy
of an object:

template<class T, class Comp>
class KeepOne
{
T theOne;
Comp C;
public:
KeepOne(T init) : theOne(init) {}
void insert(T t)
{
if (C(t, theOne))
theOne = t;
}
T& get() { return theOne; }
};

int main()
{
test<intt1(1);
test<intt2(2);

KeepOne<test<int>, std::less<test<int k(t2);
k.insert(t1);
std::cout << k.get().getpp();
}
As you can see, when you insert() into the KeepOne object it will only
keep one object and the one that it keeps is determined by the
comparator used. Replace std::less<test<int with
std::greater<test<int and you'll see that it will keep t2 instead of
t1.

Ok but the more general idea is that the point of using a Comparator is
that you don't need to change the code in the container that uses the
comparator. As long as you implement the operators in the objects being
stored you can just change the Comparator instead of writing a copy of
the container where it uses < instead og >, right?
Not quite, I'd say that the idea is more that if you have no way to
change the containers (while it's theoretically possible to change the
standard containers most people wouldn't) and you can't change the
objects to be stored either you can instead create your own comparator,
that way you can use the standard containers with any objects without
even if they were not designed to be stored in such.

--
Erik Wikström
Jun 10 '07 #4

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

Similar topics

5
by: Exits Funnel | last post by:
I've got this code: //Begin foo.cpp #include <utility> #include <bits/stl_function.h> typedef std::pair<int, int> int_pair_t; template<> struct std::less<int_pair_t> { };
5
by: Vinu | last post by:
Hi I am facing a problem in compilation the error is like this In constructor xServices::CServices<TImp>::StHoldClientList::StHoldClientList(std::set<TImp*, std::less<TImp*>,...
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:
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...
2
by: desktop | last post by:
I get this error when I run my program: red_black_tree.cpp:188: error: no matching function for call to ‘std::less<MyObj<int::less(MyObj<int>&, MyObj<int>&)’...
0
by: Juha Nieminen | last post by:
Mike Copeland wrote: Regardless of what ChipRecord is, that map will have an unambiguous ordering because the operator<() for std::string will be used. This is an iterator to a completely...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
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
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
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
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

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.