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

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.

Related

Why do I need to make this non friend == operator overload a member function to avoid "undefined reference" errors?

I have the following class, it is defined like so:
namespace ns{
class Bit{
public:
explicit Bit(bool bit);
Bit() = default;
explicit operator bool () const;
[[nodiscard]]
bool value() const;
[[nodiscard]]
Bit operator==(const Bit& rhs) const;
//friend Bit operator==(const Bit &lhs, const Bit &rhs); also doesn't work
private:
bool m_bit;
};
//doesn't work
//[[nodiscard]]
//Bit operator==(const Bit &lhs, const Bit &rhs);
}
When I define the operator == overload as a standalone function, it doesn't work, I get
undefined reference to `ns::operator==(ns::Bit const&, ns::Bit const&)'
Similar story for the friend function version.
The definition of the standalone function is as follows in the .cpp file:
ns::Bit operator==(const ns::Bit &lhs, const ns::Bit &rhs) {
return ns::Bit(lhs.value() == rhs.value());
}
The definition of the member function, which works, is as follows
ns::Bit ns::Bit::operator==(const ns::Bit &rhs) const{
return Bit(value() == rhs.value());
}
Why am I being forced to make a member function?
ns::Bit ns::operator==(const ns::Bit &lhs, const ns::Bit &rhs) {
return ns::Bit(lhs.value() == rhs.value());
}
you prototyped ns::operator== then defined ::operator==.
Only ns::operator== is found via ADL. ::operator== may also be found depending on what other == operators and what namespace you are in, adding confusion.

C++ Trick to avoid pointer comparison

I am moving a code base from one programming style to another.
We have a type called Operand defined like:
class Operand
{...};
Then we had
class OperandFactory
{
public:
const Operand *make_operand (...);
};
OperandFactory used to hash the Operand and keep it in a table. Therefore if you called make_operand with the same arguments, you would get the same pointer and pointer comparison over Operands proliferated. Now I need to add a feature that will make this infeasible. So, I implement operator== in Operand and would like to somehow generate at compile time (better) or run time (better than nothing) error if I ever do a pointer comparison on Operands. What's the best way to achieve this?
This is only to be used during this transition stage, so I don't mind if the solution looks like a hack as long as it captures all comparisons in the code base.
you can overload the address of operator to return a handle and declare the comparison of two handles (without definition). This would lead to a linker error.
#include <iostream>
class Op;
class Handle {
Op *pri_;
public:
explicit Handle(Op *o) : pri_(o) {}
Op *operator->() const { return pri_; }
Op &operator*() const { return *pri_; }
};
// force compile time errors on comparison operators
bool operator==(const Handle &, const Handle &) = delete;
bool operator!=(const Handle &, const Handle &) = delete;
bool operator>=(const Handle &, const Handle &) = delete;
bool operator<=(const Handle &, const Handle &) = delete;
bool operator<(const Handle &, const Handle &) = delete;
bool operator>(const Handle &, const Handle &) = delete;
class Op {
int foo_;
public:
explicit Op(int i) : foo_(i) { }
Handle operator&() { return Handle(this); };
void touch() const { std::cout << "foobar"; }
};
int main(int argc, char **argv) {
Op i{10};
Op j{20};
auto c = &j; // works
c->touch(); // works
(*c).touch(); // works
if (&j == &i) {
/* will not compile */
}
}
Note:
You have to fulfill the random_access_iterator requirement for Handle!
Op i{10}
Handle ref = &i;
ref++; ref--; ++ref; --ref; ref = ref + 10; ref = ref - 10; // should all work.
Adding an operator in your Operand class won't help : you want to detect comparisons of pointers to Operands. Unfortunately, native types operators can't be overloaded, and pointers are of native type. This is not the solution you're looking for.

Overloading assignment operator

We can overload assignment operator as a normal function, but we cannot overload assignment operator as a friend function. Why?
Because the C++ Standard says so, Article 13.5.3/1:
An assignment operator shall be
implemented by a non-static member
function with exactly one parameter.
Because a copy assignment operator
operator= is implicitly declared for a
class if not declared by the user
(12.8), a base class assignment
operator is always hidden by the copy
assignment operator of the derived
class.
That's all you really need to know. A friend function is not a member function, so it cannot be used to overload the assignment operator.
If you would like to write:
MyClassObject = MyFriendObject;
Then you would want to implement a constructor that takes a const reference to the friend class as it's parameter.
The difference between overloading by friend function and overloading by member function is that the calling object must be the first operand in overloading by member function, while there is no restriction in overloading by friend function. This is the reason behind the standard. Similarly, some other operators requiring the first operand to be the calling function must be overloaded using member functions (examples: =, [], ->, and ( )).
You cannot "extend" the assignment operator with a "free function" outside the class, but you can design the class so it will allow it:
Data.h
class Data {
public:
Data& operator=(const Data& lhs) { /*...*/; return *this; }
template <typename T> Data& operator=(const T& lhs) {
return assign(*this, lhs); // Magic right here...
}
private:
// ...
};
Point.h
class Point {
public:
float x,y;
Point& operator=(const Point& lhs) { x = lhs.x, y = lhs.y; return *this; }
template <typename T> Point& operator=(const T& lhs) {
return assign(*this, lhs); // Magic right here...
}
};
Assignment.h
Data& assign(const Data& lhs, const Point& rhs) {
lhs["x"] = rhs.x;
lhs["y"] = rhs.y;
return lhs;
}
Point& assign(const Point& lhs, const Data& rhs) {
rhs.query("x", lhs.x) || rhs.query(0, lhs.x);
rhs.query("y", lhs.y) || rhs.query(1, lhs.y);
return lhs;
}

operator overloading c++

I am trying to preform operator overloading in C++;
for some reason the compiles keeps on giving me the error
error: ‘bool Matrix::operator==(const Matrix&, const Matrix&)’ must take exactly one argument
Now, I know that there is some way to to it with one argument using this, but I understood that by using friend I can do it this way, but it still is not working.
Here is my code,
Thanks in advance.
class Matrix{
public:
Matrix();
friend bool operator==(Matrix &mtrx1,Matrix &mtrx2);
friend bool operator!=(Matrix &mtrx1,Matrix &mtrx2);
protected:
std::vector<Cell> _matrix;
int _row;
int _col;
};
inline bool Matrix::operator==(const Matrix& mtrx1, const Matrix& mtrx2){
/* .......... */
}
The operator== member function is declared as:
class foo {
public:
bool operator==( foo const & rhs ) const;
};
The operator== global function is declared as:
bool operator==( foo const & lhs, foo const & rhs );
Generally, the member function is declared and defined first. Then, the global function is defined in terms of the member function as
Only one between the member function and global function is declared and defined. Having both of them is ambiguous for statements like (1) in the following
foo f1;
foo f2;
bool f1EqualsF2 = (f1 == f2 ); // (1), ambiguous
and in such cases compiler returns error. In g++, the error message looks like
equals.cpp:24: error: ambiguous overload for ‘operator==’ in ‘f1 == f2’
equals.cpp:8: note: candidates are: bool foo::operator==(const foo&) const
equals.cpp:17: note: bool operator==(const foo&, const foo&)
Whenever operator== is done, its recommended to do the corresponding operator!=.
Although you've put the friend declaration inside the class, it's not a member. So the function definition should be a non-member:
inline bool operator==(const Matrix& mtrx1, const Matrix& mtrx2) {...}
You also need to add const qualifiers to the arguments of the declarations, to match those in the definition.
class Matrix{
public:
Matrix();
friend bool operator==(const Matrix &mtrx1, const Matrix &mtrx2);
friend bool operator!=(const Matrix &mtrx1, const Matrix &mtrx2);
protected:
std::vector<Cell> _matrix;
int _row;
int _col;
};
inline bool operator==(const Matrix& mtrx1, const Matrix& mtrx2){
/* .......... */
return true;
}
Pass compilation in Visual Studio 2005.
omit the const qualifier in your friend declaration
don't need Matrix:: in operation== definition
You do it with 2 parameters if you are doing it outside of the class, not as a member function.
As a member function you need only 1 parameter (the other parameter is *this)

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

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.