How do I define friends in global namespace within another C++ namespace? - c++

I'd like to define a binary operator on in the global namespace. The operator
works on a class that is defined in another namespace and the operator should get
access to the private members of that class. The problem I have is that I don't
know how to scope that global operator when making it a friend in the class definition.
I tried something like:
namespace NAME
{
class A {
public:
friend A ::operator * (double lhs, const A& rhs);
private:
int private_var;
};
}
A operator * (double lhs, const A& rhs)
{
double x = rhs.private_var;
...
}
The compiler (g++ 4.4) didn't know what to do with it. It seems that the line
friend A ::operator * ()
is evaluated as something like (pseudo-code)
(A::operator)
instead of
(A) (::operator)
If I leave out the :: in the declaration of the operator the compiling works but the operator is then in namespace NAME and not in the global namespace.
How can I qualify the global namespace in such a situation?

First, note that your operator declaration was lacking a namespace qualification for A:
NAME::A operator * (double lhs, const NAME::A& rhs)
and then the decisive trick is to add parentheses to the friend declaration like this, just as you proposed in your "pseudo-code"
friend A (::operator *) (double lhs, const A& rhs);
To make it all compile, you then need some forward declarations, arriving at this:
namespace NAME
{
class A;
}
NAME::A operator * (double lhs, const NAME::A& rhs);
namespace NAME
{
class A {
public:
friend A (::operator *) (double lhs, const A& rhs);
private:
int private_var;
};
}
NAME::A operator * (double lhs, const NAME::A& rhs)
{
double x = rhs.private_var;
}
Alexander is right, though -- you should probably declare the operator in the same namespace as its parameters.

This compiles, I assume without testing that it also works. Note the use of parentheses:
namespace NAME {class A; }
NAME::A operator * (double lhs, const NAME::A& rhs);
namespace NAME
{
class A {
public:
friend A (::operator *) (double lhs, const A& rhs);
private:
int private_var;
};
}
NAME::A operator * (double lhs, const NAME::A& rhs)
{
double x = rhs.private_var;
return rhs;
}
int main() {}
As Alexander mentions, though, your question doesn't explain why the operator isn't in namespace NAME. Either way it can be called as 1.0 * some_A_instance. So you may be creating needless trouble for yourself.

I don't know exact answer to your question.
But it's terrible bad idea to define operator outside namespace of its parameters (now you cut argument dependent lookup which is very usable for operators).

It is possible - you can enclose the declarator in parentheses: friend A (::operator * (double lhs, const A& rhs));
You also need to forward-declare both the class and the function.
namespace NAME {class A;}
NAME::A operator *(double lhs, const NAME::A& rhs);
// ...
namespace NAME
{
class A {
public:
friend A (::operator * (double lhs, const A& rhs));
private:
int private_var;
};
}
NAME::A operator *(double lhs, const NAME::A& rhs) {
//...
}
But I agree with Andreas that it would be better to define both in the same namespace if possible.

Related

What is the preferred way to override operators in C++

I was always overriding operators like this:
class MyClass {
public:
...
MyClass operator+(const MyClass&) const;
private:
int some_number = 5;
}
 
MyClass MyClass::operator+(const MyClass& rhs) const
{
return MyClass(some_number + rhs.some_number);
}
But today I realized you can create operators with the 'friend' keyword too:
class MyClass {
public:
...
friend MyClass operator+(const MyClass&, const MyClass&);
private:
int some_number = 5;
}
 
MyClass operator+(const MyClass& lhs, const Myclass& rhs)
{
return MyClass(lhs.some_number + rhs.some_number);
}
Which would be the preferred way considering I want left-sided and right-sided operators and I also (try to) follow the Core Guidelines?
The preferred way is to not even make it a friend:
MyClass operator+(MyClass lhs, Myclass const& rhs)
{
return lhs += rhs;
}
Of course, this does rely on operator+= but that is the more fundamental operation. += alters its left-hand side and should be a member.

Visual C++ | qualifier must be a base class of "Foo"

Why does the following code
class Foo {
public:
bool std::operator==(const Foo&, const Foo&);
};
comes up as an error ' qualifier must be a base class of "Foo" '
I get a different (maybe more reasonable) error message here:
main.cpp:4:48: error: invalid use of '::'
bool std::operator==(const Foo&, const Foo&);
^
You cannot arbitrarily overload binary operator function as class member operator functions (see Operator Overloading).
You cannot do this referencing the std namespace
What you probably wanted is
class Foo {
public:
bool operator==(const Foo&) const;
};
If you're really sure you want to overload this in the std:: namespace, you can write:
namespace std {
bool operator==(const Foo& op1, const Foo& op2) {
return op1.operator==(op2);
}
}
or simply overload the binary operator==() function in the global namespace:
bool operator==(const Foo& op1, const Foo& op2) {
return op1.operator==(op2);
}
In-class binary operators have an implicit Foo const & as the left-hand side. Thus, you should only include one Foo const & as a parameter, not two.
edit: also, as mentioned in the other answer, you would have to drop the std:: in this case too.

overload greater than operator with or without friend

Suppose I have the following class:
class Point{
private:
int x,y;
public:
int get_x() const {return x;}
int get_y() const {return y;}
Point() :x(0),y(0){}
Point(int x,int y):x(x),y(y){}
Point(const Point& P){
x = P.get_x();
y = P.get_y();
}
Point& operator= (const Point& P) {
x = P.get_x();
y = P.get_y();
return *this;
}
friend ostream& operator<<(ostream& os,const Point& P) {
os<<"["<<P.get_x()<<", "<<P.get_y()<<"]";
return os;
}
Point operator - (const Point &P){
return Point(x-P.get_x(),y-P.get_y());
}
friend bool operator > (const Point &A, const Point &B) {
return A.get_y()>B.get_y();
}
};
Here I used friend function. I can also use function without friend:
class Point{
...
bool operator > (const Point &B) const {
return y>B.get_y();
}
...
};
What are the differences between them in actual implementations? Also in the second method, the code won't compile without 'cont', why is that? Even after I changed the getter function into non-const function, it still won't compile without the 'const'.
As you've already noticed, comparison operator overloads can either be implemented as a member function or as a non-member function.
As a rule of thumb you should implement them as a non-member non-friend function where possible, as this increases encapsulation, and it allows (non-explicit) conversion constructors to be used on either side of the operator.
Say for instance your Point class for whatever reason had an int conversion constructor:
Point(int x);
With a non-member comparison operator you can now do the following:
Point p;
p < 3; // this will work with both a member and non-member comparison
3 < p; // this will **only** work if the comparison is a non-member function
You also seem to be confused about when to use const, again as a rule of thumb for comparison operators you should always use const wherever possible, because comparisons logically do not involve any change to the object.
As Point is a very small class you could also take it by value instead, so in order of most to least preferable your options are:
// Non-member, non-friend
bool operator>(Point const& A, Point const& B);
bool operator>(Point A, Point B);
// Non-member, friend
friend bool operator>(Point const& A, Point const& B);
friend bool operator>(Point A, Point B);
// Member
bool Point::operator>(Point const& B) const;
bool Point::operator>(Point B) const;

C++ how to write an operator that isn't a member function?

Anyone got an idea on how to write an operator for a class that isn't a member function of the class?
Just make it a free function, or a friend function. A good example of this is operator<<:
class X {
public:
int x;
}
ostream& operator<< (ostream& os, const X& x) {
os << x.x;
return os;
}
The benefit of making it a friend function is that you have direct access to private members, whereas a free function must access all members via public methods.
Arithmetic operators, stream operators, et cetera are often not members of a class. However, they may need to be friends in order to access private data members.
I prefer not to use friend and to expose methods that can be used by the operators instead. I believe this to be more in keeping with the Open/closed principle, as I could easily add a subtraction operator without editing the class.
These are handy for unit-testing, too (I can "inject" a std::ostringstream to test the output of print(), for instance).
Here is an example:
#include <iostream>
class Number
{
public:
Number(int j)
:i(j)
{
}
void print(std::ostream& os) const
{
os << i;
}
int value() const
{
return i;
}
private:
int i;
};
std::ostream& operator <<(std::ostream& os, const Number& n)
{
n.print(os);
return os;
}
Number operator +(const Number& n, const Number& o)
{
return Number(n.value() + o.value());
}
int main()
{
Number a(4), b(5), c(a + b);
std::cerr << c << std::endl;
}
Just declare the global function with the operator name:
Point operator+(Point& p, Vector& v) {
return new Point(p.x + q.i, p.y + q.j);
}
Basically, you can take the operator out of the class, and add a parameter to the beginning of the parameter list. In many cases, you will also need to declare the operator function as a friend.
For instance
class Foo
{
Foo operator +( Foo const& other );
};
becomes
class Foo
{
friend Foo operator +( Foo const&, Foo const& );
};
Foo operator +( Foo const& first, Foo const& second );
The friend statement allows the operator to still access any private or protected members needed.
Note that there are some restrictions on which operators can be overloaded in this manner. See this article for such a list.

Writing the implementation for an operator method

So I have a LongInt class that will have new definition for the + and * operators. The initialization in the header file looks like:
friend LongInt operator+(const LongInt& x, const LongInt& y);
friend LongInt operator*(const LongInt& x, const LongInt& y);
however in my implementation file, where I'm defining the methods found in the header, VS doesn't recognize the operator+ function or the operator* function as being listed in the header. I'm using the code:
friend LongInt LongInt::operator+(const LongInt& x, const LongInt& y)
{
}
and
friend LongInt LongInt::operator*(const LongInt& x, const LongInt& y)
{
}
Any ideas as to why this code wont work when I'm trying to define the operators?
The friend keyword is only used when declaring or defining the operator inside of a class; when declaring the operator as a friend inside of the class and defining it elsewhere, friend is only used on the declaration, not the definition. Also, functions declared as friend inside a class are in fact free functions in namespace scope, not class members. So, your definitions should look more like:
LongInt operator +(LongInt const& x, LongInt const& y) { /*...*/ }
LongInt operator *(LongInt const& x, LongInt const& y) { /*...*/ }
For further reading material, read over the following page: C++ FAQ: Friends
You're overriding an operator ... you "call" it using the operator:
LongInt foo;
LongInt bar;
LongInt foobar = foo + bar;