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?
Typically, you declare a namespace in a header file. If your function implementations are in a separate file, then qualify the function names, as in this example. A namespace can be declared in multiple blocks in a single file, and in multiple files.
Global scope or global namespace scope is the outermost namespace scope of a program, in which objects, functions, types and templates can be defined. A name has global namespace scope if the identifier's declaration appears outside of all blocks, namespaces, and classes.
Inline namespaces are a library versioning feature akin to symbol versioning, but implemented purely at the C++11 level (ie. cross-platform) instead of being a feature of a specific binary executable format (ie. platform-specific).
A friend function in C++ is defined as a function that can access private, protected and public members of a class. The friend function is declared using the friend keyword inside the body of the class. Friend Function Syntax: class className { ... .. ...
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With