Suppose I have a class with a private member, which is an implementation detail that clients of the class don't care about. This class is a value type and we want it to be copyable, eg
#include <boost/bimap.hpp> // some header that pulls in many other files
class MyClass {
public:
MyClass() {}
...
private:
boost::bimap<Key,Value> table;
};
Now every client of MyClass is forced to pull in lots of boost headers it doesn't really need, increasing build times. However, the class is at least copyable.
If we introduce a compiler firewall (Pimpl idiom) then we can move the #include dependency to the cpp file, but now we have to do lots more hard work due to the Rule of 5:
// no extra #includes - nice
class MyClass {
public:
MyClass() {}
// ugh, I don't want this, just make it copyable!
MyClass(const MyClass& rhs);
MyClass(MyClass&& rhs);
MyClass& operator=(const MyClass& rhs);
MyClass& operator=(MyClass&& rhs);
~MyClass() {}
...
private:
std::unique_ptr<MyClassImpl> impl;
};
Is there a technique for getting the benefits of the compiler firewall, but retaining copyability so that I don't need to include the Rule of 5 boilerplate?
I think the best solution here is to build your own deep-copying smart pointer. If you tailor it to storing Pimpls only, it shouldn't be too difficult:
Just document that it doesn't support pointing to base class subobjects, and you're set. You could enforce this by not giving it a constructor taking a pointer, and enforcing construction through
make_pimpl
: