Syntax for using overloaded operator C++ - c++

This is an overloaded operator contained in a class:
inline operator const FOO() const { return _obj_of_type_FOO; }
I cannot for the life of me understand:
How I would invoke this operator?
What would be its return value?
[Secondary] Whether making it inline affects anything apart from efficiency?

That expression looks like a declaration of a conversion operator if Foo is a type and it is inside a class. The second const (the one closer to the opening curly bracket) means that the conversion can be called on const instances. Let us say the class is C. You can think of a conversion operator as a constructor outside a class. For example, you can't add constructors to the class std::string, but you can add a conversion operator to std::string to your classes. The result is that you can construct std::string from your class instance.
1) How to invoke the conversion operator: by constructing a value of type Foo from a C, for example:
Foo foo = c (where c is an instance of C, the class that declares the conversion operator). Mind you that the invocation of the conversion can happen implicitly. If you have, for example, void funOnFoo(Foo v); and an instace c of C, this might implicitly call operator const Foo: funOnFoo(c). Whether this actually does, depends on the usual things: Whether there are other overloads of funOnFoo, other conversions for C, etc.
2) The return value is const Foo
3) inline means the same thing as for any function, in particular, does not affect overload resolution

Related

Operator overload: Member vs. non-member when only same type objects can be involved

This question gives a good answer why to define operator overloads as non-members: Operator overloading : member function vs. non-member function?
If you define your operator overloaded function as member function,
then compiler translates expressions like s1 + s2 into
s1.operator+(s2). That means, the operator overloaded member function
gets invoked on the first operand. That is how member functions work!
But what if the first operand is not a class? There's a major problem
if we want to overload an operator where the first operand is not a
class type, rather say double. So you cannot write like this 10.0 +
s2. However, you can write operator overloaded member function for
expressions like s1 + 10.0.
Now I have a situation where I need to overload operator==. In my case, only (a) objects of (b) the same type will be compared.
Is there a reason to still define operator== as a non-member or should I implement it as a member in that case?
Because operator== has symmetric semantics for its LHS and RHS argument, the recommended approach is to always implement it as a non-member in terms of the public interface of its operands (or if private data is required, to declare it as a friend inside the class).
So
class Bla
{
public:
// complete interface to data required for comparison
auto first();
auto second();
// ... more
private:
// data goes here
};
bool operator==(Bla const& L, Bla const& R)
{
return
std::forward_as_tuple(L.first(), L.second() /*, ... */) ==
std::forward_as_tuple(R.first(), R.second() /*, ... */)
;
}
This way, implicit conversion to Bla are considered for both the L and R arguments (I'm not saying implicit conversions are a good idea, but if you have those, it's better to avoid surprises where they are only considered for the RHS argument).

Problems with the conversion operator and function lookup

I have a class, let's call it Wrapper, that wraps a given type, let's say MyClass.
In reality, Wrapper is a class template, but I think that's not relevant here.
Wrapper exposes the wrapped MyClass by means of a conversion operator (just for reading).
When I create an operator for MyClass as free function (in my example a unary minus operator), this works as expected, I can use the operator also on the Wrapper class.
If I, however, implement the operator as a member function, the compiler complains: error: no match for ‘operator-’.
I thought the free function and the member function are equivalent in this case, why aren't they?
Is there a way to change the Wrapper class that a member operator or MyClass works?
If there isn't, does this suggest that it is in general preferable to implement an operator as free function instead of as member function?
Here's some code to illustrate the problem.
struct MyClass {
// This doesn't work:
void operator-() const {}
};
// It works with this instead of the member operator:
//void operator-(const MyClass&) {}
struct Wrapper {
operator MyClass() const { return MyClass(); }
};
int main() {
-Wrapper();
}
Here's a live example: http://ideone.com/nY6JzR
Question I thought the free function and the member function are equivalent in this case, why aren't they?
Answer
In order for -Wrapper() to work correctly, the compiler has to perform a lookup for operator-. It looks for the name operator- in the default namespace, in the class Wrapper, and the namespace where Wrapper is defined. It doesn't look at other classes and namespaces for the name.
That explains the compiler error when the operator-() is moved to MyClass and why it succeeds when it is defined as a non-member function.
Question Is there a way to change the Wrapper class that a member operator or MyClass works?
Answer There are two ways to resolve this.
Make the operator functions for MyClass non-member functions.
Create operator functions in MyClass as well as Wrapper, with the implementations in Wrapper being simple pass through functions. The good thing about this is that then you don't have to care whether the operator functions in MyClass are member functions or non-member functions.
Question If there isn't, does this suggest that it is in general preferable to implement an operator as free function instead of as member function?
Answer This can be a policy decision based on the choice you make to the previous answer.
I thought the free function and the member function are equivalent in
this case, why aren't they?
Lets see what happens when a conversion operator is used.
Essentially, there is a global operator function, which has a parameter of type MyClass. Now, since Wrapper has a conversion operator, the call operator-( Wrapper() ) will be inspected by overload resolution to find the best match - and overload resolution finds that there is a global operator function with parameter MyClass const& (or similiar). Then it tries to convert the Wrapper prvalue to MyClass const& and sees that there is a user-defined conversion sequence: One that uses the conversion operator to convert the Wrapper-object to a MyClass object, which then can be used to (copy-)initialize the reference.
If the operator function is a member instead, there is a problem: A global function call of the form operator-( Wrapper() ) does obviously not yield any viable functions. But the one that assumes the operator function is a member doesn't yield anything either - because operator- is not a member of Wrapper, therefore Wrapper().operator-() doesn't work and doesn't yield any viable functions either.
Remember: A class with a conversion operator does not inherit the members of the target type. If you wanted that, you should have inherited MyClass.
For a unary operator # with an operand of a type whose cv-unqualified
version is T1 [...] three sets of candidate functions, designated
member candidates, non-member candidates and built-in candidates, are
constructed as follows:
If T1 is a complete class type, the set of member candidates is the
result of the qualified lookup of T1::operator# (13.3.1.1.1);
otherwise, the set of member candidates is empty.
The set of non-member candidates is the result of the unqualified lookup of
operator# in the context of the expression according to the usual
rules for name lookup in unqualified function calls (3.4.2) except
that all member functions are ignored. [...]

Implements complex operator+(double,complex) as a member function

I've read the section 13.5 of the working draft N3797 and I've one question. Let complex be a class type which represents complex numbers. We can define the following operator function:
complex operator+(double d, complex c)
{
return *new complex(d+c.get_real(),c.get_imagine());
}
But how this operator function can be implements as a complex member function? Or must I to declare this operator function in every module which I've intend to use them?
There are two ways to define a binary operator overload, such as the binary + operator, between two types.
As a member function.
When you define it as member function, the LHS of the operator is an instance of the class. The RHS of the operator is the argument to the function. That's why when you define it as member function, it can only have one argument.
As a free function.
These functions must have two arguments. The first argument is the LHS of the operator and the second argument is the RHS of the operator.
Since double is not a class, you have to define operator+ overload between double as LHS and complex as RHS as a free function, with double const& or double as the first argument type and complex const& or complex as the second argument type.
What you're looking for is this:
inline complex operator +(double d, const complex& c)
{
return complex(d+c.get_real(), c.get_imagine());
}
This cannot be a member function if you want the operator to handle a left-side of the operator as a double. It must be a free function, possibly friended if access to anything besides the public interface of complex is needed.
If you want the right side of the add-op to be a double, a member function can be crafted:
complex operator +(double d) const
{
return complex(d+get_real(), get_imagine());
}
Note this is assuming this definition is within the body of the complex class definition. But in the interest of clarity I would recommend both be inline free functions.
Implicit Construction
Lined up with the usual suspects, what you're at-least-appearing to try to do is generally done with an implicit conversion constructor and a general free-function. By providing this:
complex(double d) : real(d), imagine()
{
}
in the class definition a double can implicitly construct a temporary complex where needed. This allows this:
inline complex operator +(const complex& lhs, const complex& rhs)
{
return complex(lhs.get_real() + rhs.get_real(),
lhs.get_imagine() + rhs.get_imagine());
}
to be used as a general solution to all sensible manifestations of what you appear to want.
In C++, operator overloading requires class types. You cannot overload the + operator for the basic type double.
Also, except in certain circumstances (short-lived programs or throwaway code), the pointer resulting from a call to the new operator should be captured, so that it can be later released with delete, preventing a situation known as a memory leak.
For it to be a member, the first parameter must be of the class type(though it is not explicitly specified). But you are sending a double as first argument. If you need this to work either make it friend function or just non-member function which can work only using public interface of the Complex class. And as others pointed out, you are leaking memory.

Operator overloading : member function vs. non-member function?

I read that an overloaded operator declared as member function is asymmetric because it can have only one parameter and the other parameter passed automatically is the this pointer. So no standard exists to compare them. On the other hand, overloaded operator declared as a friend is symmetric because we pass two arguments of the same type and hence, they can be compared.
My question is that when i can still compare a pointer's lvalue to a reference, why are friends preferred? (using an asymmetric version gives the same results as symmetric)
Why do STL algorithms use only symmetric versions?
If you define your operator overloaded function as member function, then the compiler translates expressions like s1 + s2 into s1.operator+(s2). That means, the operator overloaded member function gets invoked on the first operand. That is how member functions work!
But what if the first operand is not a class? There's a major problem if we want to overload an operator where the first operand is not a class type, rather say double. So you cannot write like this 10.0 + s2. However, you can write operator overloaded member function for expressions like s1 + 10.0.
To solve this ordering problem, we define operator overloaded function as friend IF it needs to access private members. Make it friend ONLY when it needs to access private members. Otherwise simply make it non-friend non-member function to improve encapsulation!
class Sample
{
public:
Sample operator + (const Sample& op2); //works with s1 + s2
Sample operator + (double op2); //works with s1 + 10.0
//Make it `friend` only when it needs to access private members.
//Otherwise simply make it **non-friend non-member** function.
friend Sample operator + (double op1, const Sample& op2); //works with 10.0 + s2
}
Read these :
A slight problem of ordering in operands
How Non-Member Functions Improve Encapsulation
It's not necessarily a distinction between friend operator overloads and member function operator overloads as it is between global operator overloads and member function operator overloads.
One reason to prefer a global operator overload is if you want to allow expressions where the class type appears on the right hand side of a binary operator. For example:
Foo f = 100;
int x = 10;
cout << x + f;
This only works if there is a global operator overload for
Foo operator + (int x, const Foo& f);
Note that the global operator overload doesn't necessarily need to be a friend function. This is only necessary if it needs access to private members of Foo, but that is not always the case.
Regardless, if Foo only had a member function operator overload, like:
class Foo
{
...
Foo operator + (int x);
...
};
...then we would only be able to have expressions where a Foo instance appears on the left of the plus operator.

Why are operators sometimes stand-alone and sometimes class methods?

Why is that sometimes an operator override is defined as a method in the class, like
MyClass& MyClass::operatorFoo(MyClass& other) { .... return this; };
and sometimes it's a separate function, like
MyClass& operatorFoo(MyClass& first, MyClass& bar)
Are they equivalent? What rules govern when you do it one way and when you do it the other?
If you want to be able to do something like 3 + obj you have to define a free (non-member) operator.
If you want to make your operators protected or private, you have to make them methods.
Some operators cannot be free functions, e.g., operator->.
This is already answered here:
difference between global operator and member operator
If you have a binary operator like +, you normally want type conversions to be performed on both operands. For example, a string concatenation operator needs to be able to convert either or both of its operands from a char * to a string. If that is the case, then it cannot be a member function, as the left hand operand would be *this, and would not have a conversion performed.
E.g.:
operator+( a, b ); // conversions performed on a and b
a->operator+( b ); // conversion can only be performed on b
If the operator is defined outside of a class it's considered global, and allows you to have other types appear on the left hand side of the operator.
For example, given a class Foo, with a global operator + you could do:
Foo f;
Foo f2 = 55 + f;