Ежедневный бит(е) C++ #39, Косвенный обмен: std::iter_swap
std::iter_swap
— это удобное сокращение для замены значений, на которые указывают два итератора.
В то время как исходная версия предназначена только для итераторов, версия диапазона C++20 может работать с любым косвенно перемещаемым типом и служит точкой настройки.
#include <vector> #include <iterator> #include <iostream> #include <memory> #include <ranges> template <typename It, typename Sentinel> requires std::bidirectional_iterator<It> && std::sentinel_for<Sentinel,It> void reverse(It begin, Sentinel end) { while (begin != end && std::next(begin) != end) { end = std::prev(end); // using iter_swap to swap the values behind the iterators std::iter_swap(begin,end); begin = std::next(begin); } } std::vector<int> data{1,2,3,4,5}; reverse(data.begin()+1, data.end()-1); // data == { 1, 4, 3, 2, 5 } // C++20 ranges auto a = std::make_unique<int>(7); auto b = std::make_unique<int>(42); // Generalized iter_swap, works for any indirectly movable type. std::ranges::iter_swap(a,b); // *a == 42, *b == 7 // Customization point struct Indirect { int* value_; friend void iter_swap(Indirect& l, Indirect& r) { std::cout << "Customization called.\n"; int tmp = *l.value_; *l.value_ = *r.value_; *r.value_ = tmp; } }; int x = 10, y = 20; Indirect xi(&x), yi(&y); // Calls customized iter_swap std::ranges::iter_swap(xi,yi); // x == 20, y == 10
Откройте этот пример в Compiler Explorer.