Effective C++

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 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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.
Last edited on
Thanks.
Objects of the same class can access each others private data, consider this contrived example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>

using namespace std;

class Dummy
{
public:
	Dummy() : x(0), y(0) {}
	void FuncShow(const Dummy &dum) const;
private:
	int x;
	int y;
};

void Dummy::FuncShow(const Dummy &dum) const
{
	cout << dum.x << "\t" << dum.y << endl; // "this" Dummy can access private members of "dum" Dummy
}


int main()
{
	Dummy dum1;
	Dummy dum2;

	dum1.FuncShow(dum2); // dum1 can access private members of dum2
}
Topic archived. No new replies allowed.