假设我有一个私有成员的类,这是该类客户端不关心的实现细节.这个类是一个值类型,我们希望它是可复制的,例如
#include <boost/bimap.hpp> // some header that pulls in many other files
class MyClass {
public:
MyClass() {}
...
private:
boost::bimap<Key,Value> table;
};
Run Code Online (Sandbox Code Playgroud)
现在,MyClass的每个客户端都被迫引入了许多不需要的升级头,增加了构建时间.但是,该课程至少是可复制的.
如果我们引入编译器防火墙(Pimpl idiom),那么我们可以将#include依赖项移动到cpp文件,但是由于规则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;
};
Run Code Online (Sandbox Code Playgroud)
是否有一种技术可以获得编译器防火墙的好处,但保留可复制性,以便我不需要包含5的规则样板?
我认为这里最好的解决方案是构建自己的深度复制智能指针.如果你只是将它定制为存储Pimpls,那应该不会太困难:
template <class P>
class pimpl_ptr
{
std::unique_ptr<P> p_;
public:
~pimpl_ptr() = default;
pimpl_ptr(const pimpl_ptr &src) : p_(new P(*src.p_)) {}
pimpl_ptr(pimpl_ptr &&) = default;
pimpl_ptr& operator= (const pimpl_ptr &src) { p_.reset(new P(*src.p_)); return *this; }
pimpl_ptr& operator= (pimpl_ptr &&) = default;
pimpl_ptr() = default;
pimpl_ptr(P *p) : p_(p) {}
P& operator* () const { return *p_; }
P* operator-> () const { return &**this; }
// other ctors and functions as deemed appropriate
};
Run Code Online (Sandbox Code Playgroud)
只记录它不支持指向基类子对象,并且你已经设置好了.您可以通过不给它一个构造函数来获取指针来强制执行此操作,并通过make_pimpl以下方式强制构造:
template <class P>
class pimpl_ptr
{
// as above, P* ctor is private
private:
pimpl_ptr(P *p) : p_(p) {}
template <class T, class... Arg>
friend pimpl_ptr<T> make_pimpl(Arg&&... arg);
};
template <class T, class... Arg>
pimpl_ptr<T> make_pimpl(Arg&&... arg)
{
return pimpl_ptr<T>(new T(std::forward<Arg>(arg)...));
}
Run Code Online (Sandbox Code Playgroud)