While looking at the documentation for std::swap
, I see a lot of specializations.
It looks like every STL container, as well as many other std facilities have a specialized swap.
I thought with the aid of templates, we wouldn't need all of these specializations?
For example,
If I write my own pair
it works correctly with the templated version:
template<class T1,class T2> struct my_pair{ T1 t1; T2 t2; }; int main() { my_pair<int,char> x{1,'a'}; my_pair<int,char> y{2,'b'}; std::swap(x,y); }
So what it is gained from specializing std::pair
?
template< class T1, class T2 > void swap( pair<T1,T2>& lhs, pair<T1,T2>& rhs );
I'm also left wondering if I should be writing my own specializations for custom classes,
or simply relying on the template version.
The function std::swap() is a built-in function in the C++ Standard Template Library (STL) which swaps the value of two variables. Parameters: The function accepts two mandatory parameters a and b which are to be swapped. The parameters can be of any data type.
Is specializing std::swap deprecated now that we have move semantics? No. This is the generic version, but you can optimize it to skip a third move operation.
It is not atomic. Atomic operations are not cheap and 99% of the time you do not need the atomicity. There are (IIRC) some other means to get atomic operations but std::swap() is not one of them.
To use the swap() function, we need to include the header file <utility> in our C++ program.
So what it is gained from specializing std::pair?
Performance. The generic swap is usually good enough (since C++11), but rarely optimal (for std::pair
, and for most other data structures).
I'm also left wondering if I should be writing my own specializations for custom classes, or simply relying on the template version.
I suggest relying on the template by default, but if profiling shows it to be a bottleneck, know that there is probably room for improvement. Premature optimization and all that...
std::swap
is implemented along the lines of the code below:
template<typename T> void swap(T& t1, T& t2) { T temp = std::move(t1); t1 = std::move(t2); t2 = std::move(temp); }
(See "How does the standard library implement std::swap?" for more information.)
So what it is gained from specializing
std::pair
?
std::swap
can be specialized in the following way (simplified from libc++
):
void swap(pair& p) noexcept(is_nothrow_swappable<first_type>{} && is_nothrow_swappable<second_type>{}) { using std::swap; swap(first, p.first); swap(second, p.second); }
As you can see, swap
is directly invoked on the elements of the pair using ADL: this allows customized and potentially faster implementations of swap
to be used on first
and second
(those implementations can exploit the knowledge of the internal structure of the elements for more performance).
(See "How does using std::swap
enable ADL?" for more information.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With