前言
之前我们研究了std::bind, std::move的实现原理,如有兴趣可以往前翻翻。本节讨论下std::swap, 也比较简单。
实现代码
/usr/include/c++/8/bits/move.h
158 #define _GLIBCXX_MOVE(__val) std::move(__val)
178 #if __cplusplus >= 201103L
179 typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>,
180 is_move_constructible<_Tp>,
181 is_move_assignable<_Tp>>::value>::type
182 swap(_Tp& __a, _Tp& __b)
183 noexcept(__and_<is_nothrow_move_constructible<_Tp>,
184 is_nothrow_move_assignable<_Tp>>::value)
185 #else
186 void
187 swap(_Tp& __a, _Tp& __b)
188 #endif
189 {
190 // concept requirements
191 __glibcxx_function_requires(_SGIAssignableConcept<_Tp>)
192
193 _Tp __tmp = _GLIBCXX_MOVE(__a);
194 __a = _GLIBCXX_MOVE(__b);
195 __b = _GLIBCXX_MOVE(__tmp);
196 }
可见,是通过一个中间变量来交换的,相当于:
_Tp __tmp = std::move(__a);
__a = std::move(__b);
__b = std::move(__tmp);
交换条件
这里使用了SFINAE (Substitution Failure Is Not An Error)有条件的激活swap,如果你的对象不是可移动的且编译标准大于等于c++11,也没法swap,例如:
#include<iostream>
using namespace std;
class NotSwappableType {
public:
NotSwappableType() = default;
// Delete move constructor and move assignment operator
NotSwappableType(NotSwappableType&&) = delete;
NotSwappableType& operator=(NotSwappableType&&) = delete;
};
int main(){
int a=1;
int b=2;
std::swap(a,b);
std::cout<<"a="<<a<<" b="<<b<<std::endl;
NotSwappableType nm1,nm2;
std::swap(nm1,nm2);
}
则会编译失败。