C++
iter_swap
function specialization
programming
template specialization

Can iter_swap be specialised?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

std::iter_swap swaps the values pointed to by two iterators. While you cannot legally specialize std::iter_swap itself (specializing standard library function templates in namespace std is restricted), you can achieve the same optimization effect by customizing swap for your type or, in C++20, by providing a custom iter_swap via ADL for your iterator type through std::ranges::iter_swap.

What iter_swap Does

cpp
1#include <algorithm>
2#include <vector>
3
4int main() {
5    std::vector<int> v = {1, 2, 3, 4, 5};
6
7    // Swap elements at positions 0 and 4
8    std::iter_swap(v.begin(), v.begin() + 4);
9    // v = {5, 2, 3, 4, 1}
10}

The default implementation is equivalent to:

cpp
1template<class ForwardIt1, class ForwardIt2>
2void iter_swap(ForwardIt1 a, ForwardIt2 b) {
3    using std::swap;
4    swap(*a, *b);
5}

It dereferences both iterators and calls swap on the underlying values.

Can You Specialize std::iter_swap?

Short answer: No — per the C++ standard, you are only allowed to specialize templates in namespace std for user-defined types under specific conditions, and function templates like std::iter_swap are not among the allowed specializations. Adding overloads to namespace std is undefined behavior.

cpp
1// ILLEGAL — undefined behavior
2namespace std {
3    template<>
4    void iter_swap(MyIter a, MyIter b) { /* custom swap */ }
5}

What You Can Do Instead

Option 1: Specialize swap for Your Type

Since std::iter_swap calls swap(*a, *b) using ADL, you can provide a custom swap for your type:

cpp
1class Matrix {
2    double* data;
3    size_t rows, cols;
4public:
5    // Efficient swap — just swap pointers, not data
6    friend void swap(Matrix& a, Matrix& b) noexcept {
7        using std::swap;
8        swap(a.data, b.data);
9        swap(a.rows, b.rows);
10        swap(a.cols, b.cols);
11    }
12};
13
14// Now std::iter_swap on Matrix iterators uses your efficient swap
15std::vector<Matrix> matrices = { /* ... */ };
16std::iter_swap(matrices.begin(), matrices.begin() + 1);  // Calls your swap

Option 2: Custom Iterator with iter_swap (C++20)

In C++20, std::ranges::iter_swap uses ADL to find a custom iter_swap for your iterator type:

cpp
1#include <ranges>
2
3class ProxyIterator {
4    // ...
5public:
6    using value_type = int;
7
8    // Custom iter_swap found via ADL
9    friend void iter_swap(ProxyIterator a, ProxyIterator b) {
10        // Custom swap logic for proxy references
11        auto temp = *a;
12        *a = *b;
13        *b = temp;
14    }
15};
16
17// std::ranges::iter_swap will find the friend function via ADL
18ProxyIterator it1, it2;
19std::ranges::iter_swap(it1, it2);  // Calls your custom iter_swap

This is particularly useful for proxy iterators (like std::vector<bool>::iterator) where dereferencing returns a proxy reference, not a real reference.

Option 3: ADL-Based iter_swap in Your Namespace

cpp
1namespace mylib {
2    class BigObject {
3        std::unique_ptr<Data> data_;
4    public:
5        friend void swap(BigObject& a, BigObject& b) noexcept {
6            a.data_.swap(b.data_);
7        }
8    };
9
10    // Custom iter_swap for your iterators
11    template<typename Iter>
12    void iter_swap(Iter a, Iter b) {
13        // Only matches iterators to mylib types via ADL
14        swap(*a, *b);
15    }
16}

Why Customization Matters

The default iter_swap calls swap(*a, *b). For most types, this is fine. But for:

  • Large objects: A custom swap that moves pointers instead of copying data is orders of magnitude faster
  • Proxy iterators: vector<bool>::iterator returns a proxy, not bool&. The default swap fails because you cannot take a reference to a proxy. A custom iter_swap handles this correctly.
  • Non-copyable types: Move-only types need swap to use moves, not copies
cpp
1// Without custom swap: 3 copies of a large object
2// With custom swap: 3 pointer swaps
3struct LargeBuffer {
4    std::array<char, 1000000> data;
5
6    friend void swap(LargeBuffer& a, LargeBuffer& b) noexcept {
7        // Still copies, but you could use unique_ptr internally
8        std::swap(a.data, b.data);
9    }
10};

C++20 ranges::iter_swap Customization Points

std::ranges::iter_swap follows a priority order:

  1. Custom iter_swap found via ADL (your overload)
  2. std::ranges::swap(*a, *b) if both are lvalue references
  3. std::ranges::swap with moves as a fallback
cpp
// C++20 ranges algorithms use ranges::iter_swap internally
std::vector<int> v = {3, 1, 4, 1, 5};
std::ranges::sort(v);  // Internally calls ranges::iter_swap

Common Pitfalls

  • Never specialize in namespace std: Adding specializations or overloads of std::iter_swap in namespace std is undefined behavior. Use ADL (friend functions in your type's namespace) instead.
  • Forgetting using std::swap: Inside your custom swap implementation, always write using std::swap; before calling swap on members. This enables ADL for the member types while falling back to std::swap.
  • Proxy reference issues: If your iterator returns a proxy (not a true reference), std::swap(*a, *b) may fail to compile. Use C++20 ranges::iter_swap or provide a custom iter_swap via ADL.
  • noexcept: Mark your swap as noexcept if possible. Many STL algorithms check noexcept-ness to choose between move and copy operations.

Summary

  • You cannot legally specialize std::iter_swap in namespace std
  • Instead, provide a custom swap for your type — std::iter_swap will find it via ADL
  • In C++20, provide a friend iter_swap for your iterator type — std::ranges::iter_swap will find it via ADL
  • Custom swap is essential for large objects (pointer swap vs data copy) and proxy iterators
  • Always use using std::swap; before calling swap to enable ADL lookup

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.