Minimal example:
class A
{
friend void swap(A& first, A& second) {}
void swap(A& other) {}
void call_swap(A& other)
{
swap(*this, other);
}
};
int main() { return 0; }
g++ 4.7 says:
friend.cpp: In member function ‘void A::call_swap(A&)’:
friend.cpp:7:20: error: no matching function for call to ‘A::swap(A&, A&)’
friend.cpp:7:20: note: candidate is:
friend.cpp:4:7: note: void A::swap(A&)
friend.cpp:4:7: note: candidate expects 1 argument, 2 provided
Outcomment line 4:
// void swap(A& other) {}
...and it works fine. Why, and how to fix this, if I want to keep both variants of my swap function?
I believe it is because the compiler is trying to find the function within the class. This should be a minimalistic change to make it work (it works in Visual Studio 2012):
class A; // this and the next line are not needed in VS2012, but
void swap(A& first, A& second); // will make the code compile in g++ and clang++
class A
{
friend void swap(A& first, A& second) {}
void swap(A& other) {}
void call_swap(A& other)
{
::swap(*this, other); // note the scope operator
}
};
int main() { return 0; }
As a workaround, you can declare a static version of swap. Then, you can declare the friend version to call the static version.
class A
{
public:
friend void swap(A& first, A& second) { A::swap(first, second); }
private:
static void swap(A& first, A& second) {}
void swap(A& other) {}
void call_swap(A& other)
{
swap(*this, other);
}
};
int main () {
A a, b;
swap(a, b);
}
Why
Inside the class, names scoped within the class hide those in the surrounding namespace; so the friend (whose name is scoped in the namespace, but not directly accessible there) is hidden by the member (scoped in the class) and not available as a potential overload here. (Update: or perhaps it's a bit more complicated than that, as mentioned in the comments. The scope and name lookup rules are a bit hard to follow, especially when friends are involved).
how to fix this, if I want to keep both variants of my swap function?
There's no perfect solution. If the functions both do the same thing, then just use the member from other member functions. If you declare the friend outside the class definition, then it's accessible as ::swap; but this is a bit fragile if you put the class in a different namespace. (Update: or use a static member function as suggested by this answer; I didn't think of that).
Keep to the standard swap idiom, and you won't have a problem:
void call_swap(A& other) {
using std::swap;
swap(*this, other);
}
Or use the Boost.Swap wrapper:
void call_swap(A& other) {
boost::swap(*this, other);
}
This is pretty much equivalent to #Juan's solution, except you're not writing the helper yourself.
You can also use a helper function, as in this case
template<class T>
void swap_elems(T& lhs, T& rhs)
{
using namespace std;
swap(lhs, rhs);
}
class A
{
friend void swap(A& first, A& second) { first.swap(second); }
public:
void swap(A& other) {}
void call_swap(A& other)
{
swap_elems(*this, other);
}
};
What you're observing here is that in absence of a previous declaration of a friend function, friendship within a class injects the name into the enclosing namespace, but NOT into the class scope. The only thing that happens at class scope is that the function named is granted access to private attributes.
This leaves only one swap function in the class scope (the member with one parameter) so that's the only candidate overload. Once you've found a candidate even if overload resolution fails you will never try another enclosing scope (shadowing).
If you really need both versions (and step back to make sure you do), put the implementation into a function like swap_impl which you call from the friend and the member.
Related
The following classes definitions declare a friend function providing an inline definition for it. I was trying to invoke the friend function from a class method with the same name of the friend function, but in order to make it work I have to access it from the enclosing namespace (which also requires a forward declaration, class C below). Why the name lookup works for class A and it doesn't work in class B? Note that the parameters of B::swap are different from those of its friend function.
#include <utility>
struct A {
A(int x) : v{ x } {}
friend void swap(A& x, A& y) { std::swap(x.v, y.v); }
void swapm(A& other) { swap(*this, other); }
private:
int v;
};
struct B {
B(int x) : v{ x } {}
friend void swap(B& x, B& y) { std::swap(x.v, y.v); }
void swap(B& other) { swap(*this, other); } // <-- This doesn't compile
private:
int v;
};
struct C;
void swap(C& x, C& y);
struct C {
C(int x) : v{ x } {}
friend void swap(C& x, C& y) { std::swap(x.v, y.v); }
void swap(C& other) { ::swap(*this, other); }
private:
int v;
};
int main()
{
A a1{ 1 }, a2{ 2 }; swap(a1, a2); a1.swapm(a2);
B b1{ 3 }, b2{ 4 }; swap(b1, b2); b1.swap(b2);
C c1{ 5 }, c2{ 6 }; swap(c1, c2); c1.swap(c2);
}
Whether it's a good idea or not, here's an explanation of why it's failing:
The compiler uses several different phases of processing to figure out what your program says. The reason that class B doesn't compile is because the failure that's occurring happens before the friend would be noticed. Let me explain:
When the compiler gets to the point where it's trying to figure out what swap means, it does a name lookup. It uses specific rules that specify where it should look. This is simplified, but basically it first looks for symbols defined in local scope, then in class scope, and then in enclosing (namespace, etc) scopes. It finds the one defined in class scope, and stops looking. That swap does not take those 2 parameters, so it the compilation fails.
The friend declaration, which allows the free function to access B's internals, acts as an additional declaration for the swap function that you've declared in the global namespace. These declarations would be considered by the compiler if it got to the point in name lookup where it was considering functions in the global namespace. In class B, the compiler has already stopped processing before it gets to this stage. (And the friend declaration would be necessary in an even later phase, when the compiler is working on compiling a version of the swap function that works with B objects, and wants to figure out, "in this function called swap that can take these 2 parameters; can I access B's internals?")
In class A, you're using a different name. The name lookup phase doesn't succeed until it locates your free swap function. In class C, you've given the name-lookup specific instructions, "hey, when you're looking up swap, look in global-namespace scope, and ignore the ones in local- and class-scope that you might find."
(Note: description of name-lookup and friend updated after #PeteBecker's comment.)
inline friend? Why not static in this case? And not friend? And then create a global one that calls the static. For me, this is a bad design more than an actual problem.
The method swap should be the one doing the work instead of the friend (because no need for a friend anymore):
struct C {
C(int x) : v{ x } {}
void swap(C& other) { std::swap(this->v, other.v); }
private:
int v;
};
void swap(C& x, C& y)
{
x.swap(y);
}
I have this base class (details removed)
template<class T>
class GPtr
{
public:
typedef T BaseType;
GPtr& operator=(const BaseType& rhs)
{
m_p = rhs.get();
return *this;
}
private:
BaseType m_p;
};
Then a sub-class specialises the template and adds another assignment option:
class GDrawablePtr : public GPtr<XYZ>
{
public:
GDrawablePtr& operator=(const RootType& rhs)
{
GPtr::operator =(convert<BaseType::element_type>(rhs));
return *this;
}
/* -- only compiles if this is uncommented
GDrawablePtr& operator=(const BaseType& rhs)
{
GPtr::operator =(rhs);
return *this;
}
*/
};
With that code commented out, I get compilation errors about ambiguous assignment when assigning instances. If I uncomment it, then even though it doesn't appear to do anything new, compilation is successful.
Is there a way to avoid re-defining the original base assignment operator, and what is the reason for this behaviour?
It's known as hiding: declaring a function in a derived class makes any function in the base class with the same name inaccessible. You can use a using-declaration to make the base class versions available too:
// In GDrawablePtr
using GPtr::operator=;
I am very confuse in getting the idea of operator overloading as a member and non member function.
What do we actually mean, when we overload operator as a non-member function and similarly what do we mean when we overload operator as a member functions. Although I know that the non-member functions are the friend functions.
If you overload an operator as a non-member function, you need to specify an object which you want to operate on specifically in your argument list.
If you overload it as a member function, the "this" pointer will do part of the work for you.
Consider the following example:
class Test {
public:
friend Test operator+(const Test &lhs, const Test &rhs); // Non-member function
Test operator+(const Test &rhs); // Member function
};
The difference between the two is that the non-member function doesn't have the this pointer that compiler conveniently passes for you whenever you're talking about a specific instance of a class.
The member function one has the lhs inferred, therefore you need to provide only the rhs.
Please do note that the "friend" is not necessary but if you want to access Test's private members, you need it.
Compiler can disambiguate based on the parameter count. If you wanted to declare friend Test operator+(const Test &rhs), it would complain about insufficiency of arguments because + is a binary operator. The lhs of a member function operator+ is "this".
example
class Foo {
public:
Foo operator+(Foo) // member variant
// declared inside the function
}; // end of class
Foo operator+(Foo lhs, Foo rhs) // non-member variant
{ // declared outside the class
// could be just a call to the member variant
lhs.operator+(rhs);
// I usually do this when implementing std::stream operators,
// don't remember why just now.
}
the non-member does not need to be friended but may be if it need access to internal state.
the non-member has some advantages when it comes to templated code and namespaces on some compilers if I remember correctly, It can also be fine to friend in the non-member variant to document that there is a function outside the class that is somewhat specific to this class. It tells me that if I change that class I may have to look over the non-member operator to make sure that I have not broken anything.
A small example: (I haven't tried compiling this code but I hope it works)
class MyClass
{
public:
MyClass operator+(const MyClass& other) const; //member operator declaration
friend MyClass operator-(const MyClass& first, const MyClass& second); //non-member operator friend declaration
private:
int _a;
}
//member operator definition
MyClass MyClass::operator+(const MyClass& other) const
{
MyClass result;
result._a = _a + other._a;
return result;
}
//non-member operator definition
MyClass MyClass::operator-(const MyClass& first, const MyClass& second)
{
MyClass result;
result._a = first._a - second._a;
return result;
}
Mind the differences: in the member operator definition I don't specify anything before the first _a after "=" - this->_a is assumed.
The member operator functions can be used only if an instance of your class is the first argument of the operator. If, for example you wanted to do something like 2 + myClassObject, you would need to override the non-member operator MyClass MyClass::operator+(int first, const MyClass& second) (or with whatever return value you want this to have).
Note also that I needed the friendship declaration only for my non-member operator to have an access to the private _a field.
Most operators should be defined as members.
class MyClass
{
...
public:
const MyClass& operator+=(const MyClass&);
};
Bit this is identical in behavior to the following:
class MyClass {...};
const MyClass& operator+=(const MyClass&, const MyClass&);
The implied this in the first example is analagous to the first parameter to the second example. If the second example needs access to the internal state of MyClass, it needs to be friended.
class MyClass
{
friend const MyClass& operator+=(const MyClass&, const MyClass&);
};
const MyClass& operator+=(const MyClass&, const MyClass&);
The prototypical exception to this is operator<< on std::ostream.
std::ostream& operator<<(std::ostream&, const MyClass&);
This is logically a member of your MyClass, but because of the ordering of the parameters it would have to be a non-member of both classes or a member of std::ostream. Because you can't add members to std::ostream, this must be defined as a non-member.
I have two classes (ClassA and ClassB) who both have two methods (compare and converge). These methods work exactly the same way, but these classes are not related polymorphically (for good reason). I would like to define a function template that both of these classes can explicitly instantiate as a member but I'm getting errors because the methods use "this" and when I turn them into a template the compiler throws an error because they're not member functions.
Is this impossible because of that limitation? Or is there some way to use "this" inside of a function template that is not declared as part of a template class. I've done some research and found nothing.
Logic.h
template <class T>
T* compare(const T& t) {
//stuff involving this
}
template <class T>
T* converge(const T& t,bool b) {
//other stuff involving this
}
ClassA.cpp
#include "ClassA.h"
#include "Logic.h"
//constructors
template ClassA* ClassA::compare(const ClassA& t) const;
template ClassA* ClassA::converge(const ClassA& t,bool b) const;
//other methods
classB is similar.
Any help is appreciated!
I believe you can use CRTP here. Here is an example, you can omit the friend declaration in case you can do the compare using only public members:
template<class T>
class comparer
{
public:
T* compare(const T& t)
{
//Use this pointer
bool b = static_cast<T*>(this)->m_b == t.m_b;
return NULL;
}
};
class A : public comparer<A>
{
public:
friend class comparer<A>;
A() : m_b(0)
{
}
private:
int m_b;
};
class B : public comparer<B>
{
public:
friend class comparer<B>;
B() : m_b(0)
{
}
private:
int m_b;
};
int main()
{
A a1,a2;
A* p = a1.compare(a2);
B b1,b2;
B* p1 = b1.compare(b2);
return 0;
}
You can't use this inside non-member function. What you can do is create template function and declare it as a friend of your classA and classB. But classA and classB members that are accessed by template function must have the same names.
template <typename T>
bool compare(const T& t1, const T& t2)
{
return t1.val == t2.val;
}
class A
{
public:
template <typename T>
friend bool compare(const T&, const T&);
bool compare(const A& a)
{
return ::compare(*this, a);
}
private:
int val;
};
A a1, a2;
a1.compare(a2);
What you want is impossible. Member functions must be declared and defined as members. The same goes for member function templates, from which member functions can be instantiated.
But (why) do those functions have to be members? If those functions don't need access to private stuff in these classes, make them free function templates. The whole STL (which, BTW, is but one part of the C++ standard library) is build around non-member functions and achieves a much higher level of abstraction as any OO container lib coming before it ever did.
Contrary to popular believe, non-member functions generally increase encapsulation:
If you're writing a function that can be implemented as either a member or as a non-friend non-member, you should prefer to implement it as a non-member function. That decision increases class encapsulation. When you think encapsulation, you should think non-member functions.
So can you overload operators to handle objects in multiple classes (specifically private members.)
For example if I wanted == to check if a private member in Class A is equal to objects in a vector in Class B.
For example:
bool Book::operator==(const Book& check){
return(((ISBN1 == check.ISBN1) && (ISBN2 == check.ISBN2) && (ISBN3 == check.ISBN3)
&& (ISBN4 == check.ISBN4)) || (title_ == check.title_));}
Everything in that overload is part of the Book class, however what if I wanted to do something like this.
if(*this == bookcheckout[i])
with bookcheckout being part of a Library class. The == would fail in trying to compare title_ to a title_ stored in a vector of the Library class.
It's odd because I have the program doing the exact same thing in two different places, but in one place it's working and in the other it isn't.
Answered: had to have the function that the operator was in be a member function of the same class that the operator was a member function of
If you make operator friend or member of one class, it will be able to access its private members. To access privates of both, operator will have to be free standing friend of both.
That is a bit unwieldy, so consider making public interface for interesting things instead.
(suppressed all puns about accessing private parts of multiple entities)
Here is how you can make a very friendly operator, but again, this is not a good solution.
(didn't compile the code)
class B;
class A
{
friend bool operator==(const A&, const B&);
private:
int private_;
};
class B
{
friend bool operator==(const A&, const B&);
private:
int private_;
};
bool operator==(const A& a, const B& b)
{
return a.private_ == b.private_;
} class B;
This is a better way -- just make public getters and use them in operator.
class A
{
public:
int GetPrivate() const { return private_; }
private:
int private_;
};
class B
{
public:
int GetPrivate() const { return private_; }
private:
int private_;
};
bool operator==(const A& a, const B& b)
{
return a.GetPrivate() == b.GetPrivate();
}
You also can make operator to be part of one of the classes, if you need privates from it alone.
Read up on operator overloading syntax for more.
You don't specify the type of bookcheckout, so I can't be sure, but I think that your operator== will work without change.
For instance, if the code is:
class Library
{
public:
const Book & operator[] (int i);
};
Library bookcheckout;
Then your if statement will call the operator== you have without a problem.
Yes. If you need to access private members, consider providing an appropriate public interface for them OR go for friend class. It is usually better to avoid it though. To handle a specific type, implement operator== with an instance of that type.
You can, but you would need to make either 'bool operator==(A a, B a)' 'friend' of class A if you are using a free function or make class B 'friend' of class A if you implement the comparison operator as a class member function.
You can avoid the friendship requirement by providing a public accessor to the private member in class A