Overloading operator < - c++

I experts, once again while practicing online, i encountered another problem. This is regarding function template. I am able to create the template but i am not sure how to overload appropriate operator. Please advise.
Question
A function template largestOfTree to return the largest of 3 elements of the same parameterised type. To what class can the function template be applied? Write a class trainEngine with fields for name,model,mass. Overload the appropriate operator so the largestOfThree function template can be applied to three trainEngine objects.
So far ?
template<class T>
bool largestOfThree(T t1, T t2, T t3){
if(t1<t2&&t2<t3){
return true;
}else{
return false;
}
}
trainEngine
class trainEngine {
private:
string name;
string model;
string mass;
public:
friend bool operator<(trainEngine const& lhs) {
if (lhs.name<lhs.model&&lhs.model<lhs.mass){
return true;
}
};

A friend operator< is going to be non-member and should thus be binary. Moreover, you forgot the return type. You likely want:
friend bool operator<(trainEngine const& lhs, trainEngine const& rhs) {
// implementation
}
This would go where your operator< declaration is currently.
Here is a list of idiomatic signatures for operator overloads, and a more elaborate explanation of what juanchopanza mentioned in the comments. Note that the non-member operators can be defined within the class body if they are marked as friends. (They are still non-member functions if you do this.)

If you overload operator '<', you should also overload operator '>'
and you have to write return type bool also.
friend bool operator<(trainEngine const& obj1, trainEngine const& obj2)
In fact, it’s convention in most code to prefer the usage of < over > But more generally, always overload the complete set of related operators; in your case, this would probably also be ==, !=, <= and >=.

Let me note that currently your implementation only depends on the right-hand-side (which you call lhs!). It is surely not what you want.
I think you wanted something like this:
bool operator<(trainEngine const& rhs) {
if(name!=rhs.name)
return(name<rhs.name);
if(model!=rhs.model)
return (model<rhs.model);
return (mass<rhs.mass);
}
or the friend version:
//within the class
friend bool operator<(trainEngine const& lhs, trainEngine const& rhs);
//outside the class
bool operator<(trainEngine const& lhs, trainEngine const& rhs) {
if(lhs.name!=rhs.name)
return(lhs.name<rhs.name);
if(lhs.model!=rhs.model)
return (lhs.model<rhs.model);
return (lhs.mass<rhs.mass);
}

Related

operator overloading using template

I'm writing a class named Double which extends the built in type 'double' in c++. It has a data member of the type 'double'. For the class Double I need to overload many basic arithmetic operators like "+", "-", "*", "/". For example, the "+" operator is overloaded this way:
Relation<Double>* operator+ (Double &d2)
// Relation is a abstract class template.
{
/*
...code that do something else.
*/
return new Plus<Double>(this, &d2); // Plus is derived from Relation.
}
// Double + Double returns a Relation pointer.
and the "-" operator is overloaded fast the same way:
Relation<Double>* operator- (Double &d2)
{
/*
...code that do something else but the same as above.
*/
return new Minus<Double>(this, &d2);
}
The actual calculation is done by the member function in the Relation class. The only difference of the operators' bodies is the object initialized(Plus vs Minus).
For operator that takes exactly two operands, I should alway do the overloading like this, which is duplicated and not nice.
So template function comes to my mind. But the problem is, I can pass Plus or Minus as template argument, but can not pass the operator. How could I make a template or use other methods to do the overloading of these operators?
Yes, operator overloading may be a pain and source of code duplication, see this suggestion to the standard to ease it.
For now the only I can think about is something like this:
template<typename T>
struct OperatorMinus {
static T doIt(T const& lhs, T const& rhs) { return lhs - rhs; };
}
template<typename T>
struct OperatorPlus {
static T doIt(T const& lhs, T const& rhs) { return lhs + rhs; };
}
template<typename T, typename U>
class Operator: public Relation<T>
public:
Operator(T const& lhs, T const& rhs): _lhs(lhs), _rhs(rhs) {}
T doIt() override {
return U::doIt(_lhs, _rhs);
}
private:
T _lhs;
T _rhs;
};
Relation<Double>* operator+ (Double &d2)
{
return new Operator<Double, OperatorPlus<Double>>(this, &d2);
}

Operators for non-primitive boxed types

I have the following class definition:
template <typename T>
class MyBox {
public:
MyBox(T value) { _value = value; }
operator T() const { return _value; }
private:
T _value;
};
typedef MyBox<int> MyInt;
typedef MyBox<std::string> MyString;
When I try to use operators on my typedefs like this
bool first = MyInt(1) == MyInt(1); // works
bool second = std::string(MyString("a")) == std::string(MyString("a")); //works
bool third = MyString("a") == MyString("a"); // does not compile
the compiler complains about the third comparison
no operator "==" matches these operands. operand types are: MyString == MyString
and this happens with any other non-primitve boxing (e.g. MyBox<float> works but MyBox<std::map<int,int> > not. Why is that so?
This is especially unclear to me because for the first and second comparison the operator T() is used - why can't that be done automatically for MyString as well?
UPDATE: Is there a simple solution to this other than providing the specific operators for each non-primitive template? And what to do with MyString("a") == std::string("a")?
The reasons on why it works for built-in types, but does't work for custom types is answered in the following SO quesiton: using user-defined conversions with implicit conversions in comparisons. In short, this is because type conversion does not happen for template-deduced types. And while built-in operator== for int is not a template (and thus can be found using type conversion when MyBox<int> is used), operator== for std::string is a template.
However, the question mentioned above doesn't have details on how to solve this problem. Here is how: add following free functions
template<class T>
bool operator==(const MyBox<T>& lhs, const MyBox<T>& rhs) {
return static_cast<const T&>(lhs) == static_cast<const T&>(rhs);
}
template<class T>
bool operator==(const MyBox<T>& lhs, const T& rhs) {
return static_cast<const T&>(lhs) == rhs;
}
template<class T>
bool operator==(const T& lhs, const MyBox<T>& rhs) {
return lhs == static_cast<const T&>(rhs);
}

Accepting templated arguments in function signature regardless of actual instantiation

the title may be a bit confusing so let me elaborate.
Say, I have a class template<bool is_const> foo that can take one of two forms, const or non-const based on the template parameter. This class has some operators overloaded like
bool foo<is_const>::operator==(const foo<is_const> &other) const {
return this->a == other.a;
}
The actual return value is irrelevant here. The point is I have quite a few of those operators and for none of them does it really matter what the value of is_const is for either of the two operands. So, I would like to avoid having to duplicate each operator (once for is_bool==true and once for is_bool==false). Is it possible to define the function in a way that it doesn't really matter what value is_bool has? Kind of like const foo<> &other (which doesn't work, I tried that).
You can make the operator a template:
template <bool B>
bool operator==(const foo<B> & other) const
{
return a = other.a;
}
As you discovered, it is generally preferable to have operator overloads be non-member functions, possibly friends:
template <bool A, bool B>
friend bool operator==(const foo<A> & lhs, const foo<B> & rhs)
{
return lhs.a == rhs.a;
}
you can have template method:
template<bool is_const>
class foo {
public:
template<bool is_another_const>
bool operator==( const foo<is_another_const> &other ) const;
};
Thanks to both of you, #kerek-sb and #slava. Even though your answers didn't really solve the problem it pushed me in the right direction.
The problem with your solutions is that &other is not necessarily the same class as this any more and thus has no access to private members, which is unfortunately crucial for the comparison operators to work. So I played around with making the function a friend. What I arrived at is this:
template <bool lhs_const, bool rhs_const>
friend bool operator==(const _Iterator<lhs_const>& lhs, const _Iterator<rhs_const>& rhs) {
return (lhs.m_pos == rhs.m_pos) && (lhs.m_buffer == rhs.m_buffer);
}
The friend keyword gives access to private members for both template instantiations. It's not technically a member function any more but that doesn't really matter much.

Overloading + operator on generic class in C++

I'm trying to overload the + operator in a forest class, a forest being a collection of trees, and the + operator is supposed to combine two forests into one. I have the following code as my class definition:
template<typename NODETYPE>
class Forest
{
public:
friend Forest& operator+<>(Forest&, Forest&);
friend ostream& operator<<<>(ostream&, const Forest&);
friend istream& operator>><>(istream&, Forest&);
Forest();
Forest( const Forest& otherForest);
~Forest();
void nodes(int&) const;
private:
ForestNode<NODETYPE> *root;
ForestNode<NODETYPE> *getNewNode( const NODETYPE &);
};
The following is my implementation of operator+:
template<typename NODETYPE>
Forest& operator+<>(Forest& f1, Forest& f2)
{
f3 = new Forest();
f3.root = *f1.*root;
f3.root.sibling = *f2.*root;
*f1.root = 0;
*f2.root = 0;
return f3;
}
I get the following error on compile:
|28|error: expected constructor, destructor, or type conversion before '&' token|
line 28 refers to the signature of my operator+ implementation.
I think to correct it i am supposed to add to the return type, giving:
template<typename NODETYPE>
Forest<NODETYPE>& operator+<>(Forest& f1, Forest& f2)
{
f3 = new Forest();
f3.root = *f1.*root;
f3.root.sibling = *f2.*root;
*f1.root = 0;
*f2.root = 0;
return f3;
}
But that gives me the following errors:
|28|error: declaration of 'operator+' as non-function|
|28|error: missing template arguments before '&' token|
|28|error: 'f1' was not declared in this scope|
|28|error: missing template arguments before '&' token|
|28|error: 'f2' was not declared in this scope|
Can anyone help me with this? I'd be very very thankful.
The key to writing operator+ is don't write operator+. Instead, write a copy ctor and operator+=:
template<class NodeType>
struct Forest {
//...
Forest(Forest const &other);
//...
Forest& operator+=(Forest const &other) {
// code here
return *this;
}
//...
};
Now we add operator+:
template<class NodeType>
struct Forest {
//...
friend Forest operator+(Forest a, Forest const &b) {
a += b;
return a;
}
//...
};
And that's it! Copying is usually straight-forward (sometimes by being disallowed) and it may be simpler to think in terms of += than + (you have two objects and mutate one, rather than create a third object out of two). This pattern for op+ works with any similar type, and even for similar operators such as -, *, and /.
Operator overloading can be a good or a bad thing. Good when it leads to simpler looking code. Bad when it leads to writers either overloading with incorrect semantics (yet a solution that compiles) or where the intuitive way to use the operator leads to highly inefficient code.
Note the latter statement can apply to std::string too, which could potentially make large numbers of copies, and which is why the C++03 standard states that a string does not have to be stored internally in a contiguous buffer (in the old days they used copy-on-write references to and could store such references to both strings being concatenated until required. Subsequently it was found to be non-threadsafe and making it so was more costly than simply copying the buffer so now they copy every time and are inefficient again).
(Note that the C++11 standard which recognises threading and atomic issues ensures that the underlying does need to be contiguous and null-terminated to make read operations safe).
The correct signature of operator+ (in the case all are the same type) is as follows:
T operator+( const T&, const T& );
As a member function it would be:
class T
{
// make public if necessary
T operator+( const T& rhs ) const;
};
You can implement operator+ automatically as a template whenever operator += is available with
template<typename T, typename R>
T operator+( const T& lhs, const R& rhs )
{
T copy(lhs);
return copy += rhs;
}
If you want to declare an overloaded operator of your template as a friend, this is the correct way to do it. I will show it with operator<<
// first some forward declarations, assume ostream already declared with #include <iosfwd> minimum
template< typename T > class Forest;
template< typename T > std::ostream & operator<<( std::ostream & os, const Forest<T> & for );
template< typename T> class Forest
{
friend std::ostream& operator<< <>( std::ostream&, const Forest<T> & );
//rest of class Forest
};
template< typename T >
std::ostream & operator<<( std::ostream& os, const Forest<T> & forest )
{
// implement
return os;
}
You would apply a similar technique to any other external function you wish to declare as a friend to your class, i.e.
Forwardly declare your class as a template
Forwardly declare the method as a template function
Make the function a friend using <> before the opening parentheses denoting the parameters
Implement the function after your class.
You have to provide a template arguments for all Forest parameters.
template<typename NODETYPE>
Forest<NODETYPE> operator+(Forest<NODETYPE>& f1, Forest<NODETYPE>& f2)
Also, consider making the arguments const references to make sure you do not manipulate them.
There are several questions on stackoverflow regarding friend function templates. The C++ FAQ also has a page on them that explains some basics.
You can define an operator+ template as follows:
template< class NodeType >
Forest<NodeType> operator+( Forest<NodeType> const& f1, Forest<NodeType> const& f2)
{
// Implementation.
}
Cheers & hth.,

What are C++ non-template members as used in the Barton-Nackman trick?

From wikipedia:
// A class template to express an equality comparison interface.
template<typename T> class equal_comparable
{
friend bool operator==(T const &a, T const &b) { return a.equal_to(b); }
friend bool operator!=(T const &a, T const &b) { return !a.equal_to(b); }
};
class value_type
// Class value_type wants to have == and !=, so it derives from
// equal_comparable with itself as argument (which is the CRTP).
: private equal_comparable<value_type>
{
public:
bool equal_to(value_type const& rhs) const; // to be defined
};
This is supposed to be the Barton-Nackman, that could achieve compile-time dimensional analysis (checking if some operations applied to variables end up in comparable numbers, like speed comparable to space/time but no acceleration).
Could anyone explain me how, or at least explain me what are the NON-TEMPLATE members?
Thanks
The rules of the language have changed since the pattern was invented, although care was taken not to break it. In other words, as far as I can tell, it still works but for different reasons than it originally did. I don't think I would base an attempt at dimensional analysis on this pattern as I think there are better ways of doing that today.
I also think the example is too trivial to be helpful. As already stated the instantiation of equal_comparable<value_type> causes operator== and operator!= for value_type to appear. Since they are non-members it doesn't matter that the inheritance is private, they're still eligable for selection when resolving a call. It's just hard to see the point in this example. Let's say however, that you add a template parameter to equal_comparable and a few other things:
template<typename U, typename V> class equal_comparable
{
friend bool operator==(U const &a, V const &b) { return a.equal_to(b); }
friend bool operator!=(U const &a, V const &b) { return !a.equal_to(b); }
};
class some_other_type
{
bool equal_to(value_type const& rhs) const;
};
class value_type
: private equal_comparable<value_type>, // value_type comparable to itself
private equal_comparable<some_other_type> // value_type comparable to some_other_type
{
public:
bool equal_to(value_type const& rhs) const;
bool equal_to(some_other_type const& rhs) const;
};
Disclaimer: I have no idea if this is the way it's supposed to be used but I'm reasonably sure that it would work as described.
These are actually nontemplate nonmembers - the comparison operators in the base template - they get used by the ADL for the derived class. A template member would be something like:
class C
{
...
template < typename T > void DoGreatStuff( T t ) { ... }
...
};
The instantiation of equal_comparable<value_type> in value_type class causes the compiler to generate two comparison functions:
friend bool operator==(value_type const &a, value_type const &b) { return a.equal_to(b); }
friend bool operator!=(value_type const &a, value_type const &b) { return !a.equal_to(b); }
These functions are nontemplate since they do not depend on any template parameter, but they are also nonmembers since they are declared as friend.