This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of LEWG status.
swap overloads for indirect and polymorphic only found by ADLSection: 20.4.1.7 [indirect.swap], 20.4.2.7 [polymorphic.swap] Status: LEWG Submitter: Jonathan Wakely Opened: 2025-05-01 Last modified: 2025-10-14
Priority: 2
View all issues with LEWG status.
Discussion:
The non-member swap overloads for std::indirect and std::polymorphic
are defined as hidden friends, so are only available via ADL.
This means that calling std::swap(i1, i2) will always use the generic
std::swap instead of the custom overload for std::indirect.
[2025-10-14; Reflector poll]
Set priority to 2 after reflector poll. Status New → LEWG.
This is a broader issue than just std::indirect and std::polymorphic,
it also affects std::jthread, std::mdspan, move_only_function, copyable_function, node-handle, inplace_vector,
flat_map and co., and maybe more.
Are we comfortable that defining swap as a hidden friend means that
the generic std::swap might be suboptimal,
and for allocator-aware types might even do something with different effects?
e.g. if propagate_on_container_swap is true but
propagate_on_container_move_assignment is false.
Proposed resolution:
This wording is relative to N5008.
Modify 20.2.2 [memory.syn] as indicated:
// 20.4.1, class template indirect template<class T, class Allocator = allocator<T>> class indirect; template<class T, class Allocator> constexpr void swap(indirect<T, Allocator>& lhs, indirect<T, Allocator>& rhs) noexcept(see below); // 20.4.1.10, hash support template<class T, class Alloc> struct hash<indirect<T, Alloc>>; // 20.4.2, class template polymorphic template<class T, class Allocator = allocator<T>> class polymorphic; template<class T, class Allocator> constexpr void swap(polymorphic<T, Allocator>& lhs, polymorphic<T, Allocator>& rhs) noexcept(see below);
Modify 20.4.1.2 [indirect.syn] as indicated:
// 20.4.1.7, swap constexpr void swap(indirect& other) noexcept(see below);friend constexpr void swap(indirect& lhs, indirect& rhs) noexcept(see below);
Modify 20.4.1.7 [indirect.swap] as indicated:
template<class T, class Allocator> constexpr void swap(indirect<T, Allocator>& lhs, indirect<T, Allocator>& rhs) noexcept(noexcept(lhs.swap(rhs)));-3- Effects: Equivalent tolhs.swap(rhs).
Modify 20.4.2.2 [polymorphic.syn] as indicated:
// 20.4.2.7, swap constexpr void swap(polymorphic& other) noexcept(see below);friend constexpr void swap(polymorphic& lhs, polymorphic& rhs) noexcept(see below);
Modify 20.4.2.7 [polymorphic.swap] as indicated:
template<class T, class Allocator> constexpr void swap(polymorphic<T, Allocator>& lhs, polymorphic<T, Allocator>& rhs) noexcept(noexcept(lhs.swap(rhs)));-3- Effects: Equivalent tolhs.swap(rhs).