1.普通的交换
class WidgetImpl1 {
public:
private:
int a , b, c;
std::vector<double> v;
};
class Widget1 {
public:
Widget1(const Widget1& rhs) = default;
Widget1& operator=(const Widget1& rhs)
{
*pImpl = *(rhs.pImpl);
return *this;
}
private:
WidgetImpl1 * pImpl;
};
void dosomesing(Widget1 &a, Widget1&b)
{
using namespace std;
swap(a,b);
}
问题:真正需要置换的是pimpl,如果用默认的std::swap, 置换了三次Widget,解决方案特化std::swap函数
2、全特化std::swap,需要访问私有变量
class WidgetImpl2 {
public:
private:
int a , b, c;
std::vector<double> v;
};
class Widget2 {
public:
Widget2(const Widget2& rhs) = default;
Widget2& operator=(const Widget2& rhs)
{
*pImpl = *(rhs.pImpl);
return *this;
}
private:
WidgetImpl2 * pImpl;
};
/*
namespace std {
template <>
void swap<Widget2> (Widget2& a, Widget2& b) {
// 编译不通过, 访问了私有的pImpl,错误信息: 'pImpl' is a private member of 'Widget2'
swap(a.pImpl, b.pImpl) ;
}
}; //end std
void dosomesing(Widget2 &a, Widget2&b)
{
using namespace std;
swap(a,b);
}
*/
全特化的规律: <>中的是空的, swap后面是 目前这个版本无法编译过,应为pImpl是私有成员,解决办法有: 1、 将pImpl公开 2、将swap声明为frend 3、另Widget生成一个swap函数,本次采用的方案
3、widget内部总结swap函数,std::swap调用WidgetImpl3的swap函数;如果widget是模版,函数不能偏特化
class WidgetImpl3 {
public:
private:
int a , b, c;
std::vector<double> v;
};
template <typename T>
class Widget3 {
public:
Widget3(const Widget3& rhs) = default;
Widget3& operator=(const Widget3& rhs)
{
*pImpl = *(rhs.pImpl);
return *this;
}
void swap( Widget3& rhs)
{
using std::swap;
swap(this->pImpl, rhs.pImpl);
}
private:
WidgetImpl3 * pImpl;
};
/*
namespace std {
template <typename T>
void swap<Widget4<T>> (Widget4<T>& a, Widget4<T>& b) {
//Function template partial specialization is not allowed
}
};
*/
/*
上面的代码如果Widget是模版的话,无法编译通过。因为函数不能偏特化, 原因是重载更复杂了。
*/
// 打算偏特化, 惯例的做法是提供一个重载的版本
namespace std {
template <typename T>
void swap (Widget3<T>& a, Widget3<T>& b) {
a.swap(b);
}
};
4、放到命名空间中
namespace WidgetStuff {
class WidgetImpl4 {
public:
private:
int a , b, c;
std::vector<double> v;
};
template <typename T>
class Widget4 {
public:
Widget4(const Widget4& rhs) = default;
Widget4& operator=(const Widget4& rhs)
{
*pImpl = *(rhs.pImpl);
return *this;
}
void swap( Widget4& rhs)
{
using std::swap;
swap(this->pImpl, rhs.pImpl);
}
private:
WidgetImpl4 * pImpl;
};
template<typename T>
void swap(Widget4<T> &a, Widget4<T>& b)
{
a.swap(b);
};
// argument-dependent lookup
} //end WidgetStuff
通用的思路:
- 类内定义一个swap函数
- 命名空间总提供一个swap函数