Can iter_swap be specialised?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
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
The default implementation is equivalent to:
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.
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:
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:
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
Why Customization Matters
The default iter_swap calls swap(*a, *b). For most types, this is fine. But for:
- Large objects: A custom
swapthat moves pointers instead of copying data is orders of magnitude faster - Proxy iterators:
vector<bool>::iteratorreturns a proxy, notbool&. The defaultswapfails because you cannot take a reference to a proxy. A customiter_swaphandles this correctly. - Non-copyable types: Move-only types need
swapto use moves, not copies
C++20 ranges::iter_swap Customization Points
std::ranges::iter_swap follows a priority order:
- Custom
iter_swapfound via ADL (your overload) std::ranges::swap(*a, *b)if both are lvalue referencesstd::ranges::swapwith moves as a fallback
Common Pitfalls
- Never specialize in namespace std: Adding specializations or overloads of
std::iter_swapin namespacestdis undefined behavior. Use ADL (friend functions in your type's namespace) instead. - Forgetting
using std::swap: Inside your custom swap implementation, always writeusing std::swap;before callingswapon members. This enables ADL for the member types while falling back tostd::swap. - Proxy reference issues: If your iterator returns a proxy (not a true reference),
std::swap(*a, *b)may fail to compile. Use C++20ranges::iter_swapor provide a customiter_swapvia ADL. - noexcept: Mark your
swapasnoexceptif possible. Many STL algorithms checknoexcept-ness to choose between move and copy operations.
Summary
- You cannot legally specialize
std::iter_swapin namespacestd - Instead, provide a custom
swapfor your type —std::iter_swapwill find it via ADL - In C++20, provide a friend
iter_swapfor your iterator type —std::ranges::iter_swapwill 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 callingswapto enable ADL lookup

