Scott meyers's Effective C++ 3rd edition, Item 25 : Consider support for a non-throwing swap.
There's a piece of code with which the author is trying to explain how to efficiently a swap pointers to implementation. Here is the code which won't compile ( as he mentions ) because the data members are private :
class WidgetImpl { // class for widget data;
public:
...
private:
int a, b, c; // possibly lots of data
std::vector<double> v; // expensive to copy
...
};
class Widget { // class using the pimpl idiom
public:
Widget(const Widget& rhs);
Widget& operator=(const Widget& rhs) // to copy a widget, copy its
{ // WidgetImpl objec.
...
*pImpl = *(rhs.pImpl);
...
}
...
private:
WidgetImpl *pImpl; // ptr to object with this
}; // Widget's data
namespace std {
template<> // this is a specialized version
void swap<Widget>(Widget& a, // of std::swap for when T is Widget
Widget& b)
{
swap(a.pImpl, b.pImpl); // to swap Widget, swap their
} // pimpl pointer; this wont' compile because the pImpls are private
}
What got my attention was the solution he provides for this problem, which is
to provide a public swap function that does the actual swapping and have the std swap call it :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
class Widget {
public:
...
void swap(Widget& other)
{
using std::swap; // the need for this declaration is explained later in this item
swap(pImpl, other.pImpl); // to swap Widgets, swap their pimpl pointer
}
...
};
namespace std {
template<> // revised specialization of std::swap ( point : this is complete specialization )
void swap<Widget>(Widget& a,
Widget& b)
{
a.swap(b); // to swap Widgets, call their swap member function
}
}
Its the following line of code that actually got my attention :
(line 7) swap(pImpl, other.pImpl);
Am I missing something or Is he really erroneously trying to access "other"'s
private data member "pImpl" ?
Am I missing something or Is he really erroneously trying to access "other"'s
private data member "pImpl" ?
You're missing something. It is perfectly legal to access a Widget's private data from inside a member function, whether it is this->pImpl or other.pImpl
You may want to consider how a copy constructor or assignment operator could be implemented if it was not.