How to make set:: find() work for custom class objects? - c++

I'm a bit confused about using STL set::find() for a set of my own defined class objects.
My class contains more than two items (3/4/5 etc.), so how can I overload less operator?
I tried for 3 variable, which is as follows and working fine:
return( (a1.i < a2.i) ||
(!(a1.i > a2.i) && (a1.f < a2.f)) ||
(!(a1.i > a2.i) && !(a1.f > a2.f) && (a1.c < a2.c)));
where, a1, and a2 are class objects and (i, f and c are class members).
Now I want to generalize this for n members, but my find() does not always work.
I've been looking through STL's detailed documentation, trying to learn how set::find() is implemented, and why it needs less (<) operator overloading.
I referred to sgi and msdn documentation, but I could not find much about implementation details of set::find() there, either.
What am I doing wrong in my set::find() implementation?

You can use a tuple to easily get an lexicographical ordering of your members:
return std::tie(lhs.i, lhs.f, lhs.c) < std::tie(rhs.i, rhs.f, rhs.c);
This requires that every member be of a comparable type, e.g. lhs.i < rhs.i makes sense.
Note that std::tie and std::tuple are only available for C++11, so for C++03 you can use e.g. Boost.Tuple which does provide a boost::tie (boost::tuple uses the same ordering as std::tuple).
As to where this should go, it is customary to put that in an operator< (after all this is what make the use of tie for an easy ordering possible in the first place). Quite often this operator will be a friend, so this would look like:
class foo {
public:
/* public interface goes here */
// declaration of non-member friend operator
// if it doesn't need to be a friend, this declaration isn't needed
friend
bool operator<(foo const& lhs, foo const& rhs);
private:
T t;
U u;
V v;
};
bool operator<(foo const& lhs, foo const& rhs)
{
// could be boost::tie
return std::tie(lhs.t, lhs.u, lhs.v) < std::tie(rhs.t, rhs.u, rhs.v);
}
As you can see it's not fully automatic as the implementation of operator< needs to list every member of foo (or at least those that matter for the ordering), twice. There isn't a better way I'm afraid.
Instead of providing an operator< you can specialize std::less for foo but that's a bit exotic and not the preferred way. If the ordering would still not make sense to be part of the extended interface of foo (e.g. there might be more than one ordering that makes sense without a canonical one), then the preferred way is to write a functor:
struct foo_ordering {
bool operator()(foo const& lhs, foo const& rhs) const
{
/* implementation as before, but access control/friendship
has to be planned for just like for operator< */
}
};
Then you'd use e.g. std::set<foo, foo_ordering>.
Be aware that no matter what form the ordering takes (through either operator<, std::less<foo> or a functor) if it is used with an std::set or any other associative container (and by default e.g. std::set<T> uses std::less<T> which in turn uses operator< by default) it must follow some stringent criteria, i.e. it must be a strict weak ordering. However if all the members that are used for the foo ordering themselves have SW orderings then the resulting lexicographical ordering is also a SW ordering.

You have to define a strict ordering of your objects. So if your object is made up of n members a_1 .. a_n which all have a strict ordering themselves, what you can do is:
bool operator< (const TYPE &rhs) {
if (a_1 < rhs.a_1) return true; else if (a_1 > rhs.a_1) return false;
if (a_2 < rhs.a_2) return true; else if (a_2 > rhs.a_2) return false;
...
if (a_n < rhs.a_n) return true;
return false;
}
Edit:
If either boost or C++11 is an option for you, you should really go with the std::tie/boost::tie method Luc Danton suggests in his answer. It's much cleaner.

std::set element comparison function should define Strict Weak Ordering relation on elements domain. Using this definition we can say that two elements are equivalent if compare( a, b ) is false and compare( b, a ) is false too. std::find can be implemented using this assumption.
You can find more here: http://www.sgi.com/tech/stl/set.html and http://www.sgi.com/tech/stl/StrictWeakOrdering.html

Your operator < should be capable to compare every object with given one, like that
struct Data
{
bool operator < (const Data& right) const
{
return( (this.i < right.i) ||
(!(this.i > right.i) && (this.f < right.f)) ||
(!(this.i > right.i) && !(this.f > right.f) && (this.c < right.c)));
}
}
Also, your compare algorithm looks doubtful, because it doees not consider cases, when
this.i == right.i
or
this.f == right.f
And you actually should not be interested in std::set implementation. It can change from compiler to compiler and can be modified in future. Your program should make assumptions only about container interface, never implementation.

This is only a partial answer, but a detailed documentation of STL can be found on the website of SGI.

Related

Should comparison be implemented under `compare` or `operator ==` when both are needed?

In making a class, the compare method and the operator== overload should have identical functionality. Therefore, only one implementation is needed, and I'm trying to figure out if there's any reason why it should be defined in the compare method rather than the operator== overload.
Here's the structure defining comparison in compare:
class T {
// definition of field f
...
bool compare(const T& t) const {
if (this->f == t.f) { return true; }
return false;
}
friend bool operator == (const T& lhs, const T& rhs) { return lhs.compare(rhs); }
}
versus in the operator == overloading:
class T {
// definition of field f
...
bool compare(const T& t) const { return *this == t; }
friend bool operator == (const T& lhs, const T& rhs) {
if (lhs.f == t.f) { return true; }
return false;
}
}
TL;DR use second variant with 'virtual' keyword, but it will be better to get rid of this bullshit at all and use operator== only
You should use method compare() only if you have other variant of objects comparison, otherwise it does not make any sense. The reason for this is implementation of std::map, std::set, sorting alghoritms, etc., which use operator==, so if you use first variation of == implementation it will be, basicaly, your operator==, but with other name, which does not make any sense.
If you still want to do it,
-You can use first variant(where == uses compare), but make compare method virtual. In this case you will be able to overload comparison method just like in Java and it will affect on comparison, but still you can do it just by creating operator== for children class, so it still doesn't make any sense
...or you can use second one, but still using 'virtual' keyword to change implementation of parent class in children classes and if you don't like == implementation you can use compare method
Not very relatable example, but I think it might help you. In OpenCV library assignment operator= for class Mat(this class contains literally array of pixels and nothing more) don't actually copies array, but copies only a pointer on array of pixels(because it's heavy operation and it doesn't required in many cases), and for actual copying method clone() used. I think you can use the same solution for your code

Which operators should I implement in my class?

I have created my own class like this:
template<class T>
class ball
{
T size;
T price;
};
Now I want to support comparing two balls only according to the first value size in this case should I implement all those operators for ball class??
==, !=, >=, <=, >, <
This doesn't sound efficient or correct.
Which operators should I implement in my class?
In general, at minimum you should implement those operators which you use. And the ones that are required by concepts that you need the class to fulfill.
If you want the class to be equality comparable, then ideal design is to also let the class be comparable using operator!= and if you want the class to be comparable with ordered relations, then ideal design is to let the class be comparable with all operators.
should I implement all those operators for ball class??
Pre-C++20: Yes, this is a good idea if you want the class to be comparable.
Since C++20: No, you should in most cases only implement operator<=>. Preferably as defaulted.
I want to support comparing two balls only according to the first value size
I recommend to not define the comparison operators to behave this way. It will be highly confusing to the users of your class as they will likely expect the price to affect the equality of the object.
If you need this kind of comparison for a specific use case, then I recommend using a custom comparison object instead.
Another solution is to implement a method supporting all cases. An advantage would be that you could choose the test dynamically at runtime :
// in .hpp
typedef enum { Equal, LessOrEqual, GreaterOrEqual, NotEqual, GreaterThan, LessThan } Comparator;
bool compare(ball & a, ball & b, Comparator c = Equal);
// in .cpp
bool compare(ball & a, ball & b, Comparator c) {
bool r;
switch(c) {
case GreaterOrEqual: case LessThan: r = a.size >= b.size; break;
case LessOrEqual: case GreaterThan: r = a.size <= b.size; break;
default: r = a.size == b.size; break;
}
return c >= NotEqual ? !r : r;
}

C++ std::copy from std::deque to std:;set

I have a class with "array of array" private member represented as:
std::deque<std::deque<SomeClass> > someArray_;
Also this class have a public method which allows to receive all unique SomeClass instances, containing in someArray_. Unique for SomeClass instances means different by at least one of several class members. I decided to use std::set for that purpose. This method has prototype like following:
std::set<SomeClass> getAllUniqueInstances() const;
In this method implementation I use following construction to populate std::set:
std::set<SomeClass> allUniqueInstances;
for(auto it = std::begin(someArray_); it != std::end(someArray_); ++it){
std::copy((*it).begin(),
(*it).end(),
std::inserter(allUniqueInstances, allUniqueInstances.end()));
}
operator<() is defined for SomeClass class. As a result my std::set is populated, but huge amount of instances is missed. Modyfing operator<() for SomeClass class, alters situation, but breaks desirable sorting order. How in this case std::copy determines whether considerable instance is unique?
UPD: source code for SomeClass
class SomeClass{
private:
uint32_t from_;
uint32_t to_;
double capacity_;
double flow_;
public:
...
bool operator<(const SomeClass& rhs) const;
...
};
I want SomeClass instances to be ordered in set by from_ member:
bool SomeClass::operator<( const SomeClass& rhs ) const{
if(this->from_ < rhs.from_)
return true;
return false;
}
It is not std::copy who decides whether instances are unique, but std::set. The logic is something like
(A < B is false) and (B < A is false)
So the criterion that defines the ordering also defines the "uniqueness". It seems like std::set is the wrong data structure for this problem, or your ordering criteria are either incorrect (as in not implementing strict weak ordering), or too broad to suit the problem (as in, you order based on a small number of attributes when you could use more).
Here is an example of a lexicographical comparison using more attributes than you currently have:
#include <tuple> // for std::tie
bool SomeClass::operator<( const SomeClass& rhs ) const
{
return std::tie(from_, to_, capacity_, flow_) < std::tie(rhs.from_, rhs.to_, rhs.capacity_, rhs.flow_);
}

How to check if two stacks are the same in C++?

I am working with stacks and need to check to see if two are the same. I have overloaded the
bool operator==
function in my code, and now I need to put the logic in the code. I will check a few things to see if the two stacks are the same: the length, the data type, and the content of each element. Length and content are no problem, its the data type that is giving me issues.
I tried to make a function:
...
Type getType();
};
template <class Type>
Type getType(){ returnType;}
But this did not work.
I also thought about:
bool operator== (stack<Type> &lhs, stack<Type> &rhs){
return (lsh.Type == rhs.Type);
//additional conditions will be checked.
}
How to I check if they are the same type?
EDIT: What if I just checked the data type of the top elements of the two stacks? would that be sufficient?
If you implement operator== like this:
template<typename Type>
bool operator== (const stack<Type> &lhs, const stack<Type> &rhs){
// compare and return.
}
You already know that both stacks will contain elements of the same type. There's no need to check for that.
If you want to allow stacks using different template arguments to be compared, you could do something like this:
template<typename Type1, typename Type2>
bool operator== (const stack<Type1> &lhs, const stack<Type2> &rhs){
// compare
}
Then compare the elements using operator== and you'll be done. Of course, if there's no operator== for parameters of type Type1 and Type2, then the compiler will issue an error.
Edit: Since you want a nice error message, you could do this(using C++11):
#include <type_traits>
template<typename Type1, typename Type2>
bool operator== (const stack<Type1> &lhs, const stack<Type2> &rhs){
// This is a compile time assert!
static_assert(std::is_same<Type1, Type2>::value, "Types are not equal!");
// compare
}
I'd avoid this anyway. It's simpler to let the compiler issue its own error, rather than doing this check yourself.
C++ is not like other (dynamic) languages in that you do not need to check types. If two stacks contain different types, your code will not compile if you try to compare them. In other words, skip this step, the compiler will do it for you.
If you implement the stack data structure using templates (e.g. template <typename T> class Stack...), then you just need to overload operator== and check sizes and do an item-wise comparison:
template <typename T>
bool operator==(const Stack<T> & lhs, const Stack<T> & rhs)
{
if (lhs.Size() != rhs.Size())
return false;
// Compare item by item
...
}
The type will be implicitly checked by the C++ compiler type system (if you have a Stack<int> and try to compare against a Stack<string> you will have a compiler error).
I found a simple program which will solve your purpose, Its simple and very efficient way of checking if two stacks are equal or not.
bool isEqual(stack<Type> &stack1, stack<Type> &stack2) {
if (stack1.empty() && stack2.empty())
return true;
else if (stack1.empty() || stack2.empty())
return false;
while (!stack1.empty() && !stack2.empty())
{
if (stack1.top() != stack2.top())
return false;
stack1.pop();
stack2.pop();
}
if (stack1.empty() && stack2.empty())
return true;
else
return false;
}
As you can see in C++ tag definition of stackoverflow
C++ is a widely-used, statically-typed, free-form, compiled,
multi-paradigm, multi-level, imperative, general-purpose,
object-oriented programming language.
In this definition statically-typed mean all type information must be clean in compile time so in C++ if you want to have container of different types or you want to compare containers of different types, you must identify it in compile time through use of templates.
So when you are comparing 2 different type of containers (here stack) you know type of both containers and you do not need to compare their types. So if you want containers of different types, they should all derive from same class so they can stored as same type or you must hold them as void* (this is very dangerous unless you know what you are doing). in case that you derive all classes from same class, you can simply make base class polymorphic (by adding at least one virtual function) and use typeid to get type of object or you can add a virtual function that do comparison and then specialize it in each derived class (or even you can mix both techniques) but in case of void* you must have another way to identify type of objects!

(C++) What's the difference between these overloaded operator functions?

What is the difference between these two ways of overloading the != operator below. Which is consider better?
Class Test
{
...//
private:
int iTest
public:
BOOL operator==(const &Test test) const;
BOOL operator!=(const &Test test) const;
}
BOOL operator==(const &Test test) const
{
return (iTest == test.iTest);
}
//overload function 1
BOOL Test::operator!=(const &Test test) const
{
return !operator==(test);
}
//overload function 2
BOOL Test::operator!=(const &Test test) const
{
return (iTest != test.iTest);
}
I've just recently seen function 1's syntax for calling a sibling operator function and wonder if writing it that way provides any benefits.
Your first overload ensures that calling != on your type will always provide the opposite of calling == even if your implementation of == would change.
Your second overloaded function does not, since it is possible to provide any implementation for == and change the existing implementation in the future.
If you want to ensure that != will always be the opposite of ==, go with the first (at the cost of an extra function call which may very well become inlined anyway).
Here is a good example. Suppose that you have a class Point2D with fields x and y. If you want to implement ==, you will have to compare on field x and on field y. If you implement != by calling operator==, you have shorter code, and will have one function less to change if you ever moved to a polar representation.
Equality tests and comparisons are always susceptible to maintenance errors as the class fields change. Minimizing the number of methods that directly access state can reduce the risk of errors.
They will almost certainly compile to the same machine code.
I prefer choice 2, just because I find it awkward to say "operator==". But you could have used
return ! (*this == test)
And IMHO that's also clear and easy to understand.
I can think of many reasons (or perhaps aspects of the same reason) to write it that way. What they all boil down to is: it's DRY.
It ensures that two objects are always either == or !=
If you decide to change what's in the class, or what's used for equality testing, you only have to change it in one place
I think that conceptually, you really have two different things you're defining here:
A definition of "equality" for class Test
A useful interface by which people using this class can determine equality of their instances
With method 2, you're doing both ad-hoc. With method 1, you're defining equality in operator==, and providing the rest of the interface via operator!=.
Some languages/libraries take it even further, e.g., in Ruby you can define just <=> to compare ordered objects and mix-in Comparable and get equality, inequalities, and between?.
Version #1, while syntacticly ugly IMHO, allows you to change the equality logic in a single place (in the == operator overload). It guarantees the two overloads are always in sync.
In general, the following statement:
return !(*this == object);
allows you to define != in terms of one function. In the world of inheritance, child objects would only need to define operator== in order to use the base class operator!=:
struct Base
{
virtual bool isEqual(const Base& other) const = 0;
bool operator==(const Base& other) const
{
return isEqual(other);
}
bool operator!=(const Base& other) const
{
return !(*this == other); // Uses Base::operator==
}
};
With the above base class, defining operator!= using != would require descendants to implement more methods.
Also, !(*this == other) allows one to define a global, generic function for !=:
template <typename T>
bool operator!=(const T& a, const T& b)
{
return !(a == b);
}
Although this pattern doesn't provide much for == and !=, the differences are larger when using the relational operators: <, <=, >, >=.
In general, it is always better to implement related functionality in terms of each other. In case of operators, there are always groups. For example, != can be implemented in terms of ==; post-increment can be implemented in terms of pre-increment; >, <= and >= can be implemented in terms of < (see std::rel_ops in <utility>) etc. If something about the class needs changing, you only need to modify the core operators, and all the rest will automatically be updated to reflect the new behavior.
The general implementation of all the "secondary" operators is always the same, and so there is even a library which automatically provides operators that are defined in terms of a few provided ones. See Boost.Operators
Your example:
#include <boost/operators.hpp>
class Test : boost::equality_comparable<Test, Test>
{
private:
int iTest;
public:
bool operator==(const Test& test) const;
//look, no operator !=
};
int main()
{
Test a, b;
a != b; //still works
}