swap
undefined for most containersSection: 23 [containers] Status: C++11 Submitter: Alisdair Meredith Opened: 2008-01-14 Last modified: 2016-01-28
Priority: Not Prioritized
View other active issues in [containers].
View all other issues in [containers].
View all issues with C++11 status.
Discussion:
It appears most containers declare but do not define a member-swap function.
This is unfortunate, as all overload the swap
algorithm to call the
member-swap function!
(required for swappable
guarantees [Table 37] and Container Requirements
[Table 87])
Note in particular that Table 87 gives semantics of a.swap(b)
as swap(a,b)
,
yet for all containers we define swap(a,b)
to call a.swap(b)
- a circular
definition.
A quick survey of clause 23 shows that the following containers provide a definition for member-swap:
array queue stack vector
Whereas the following declare it, but do not define the semantics:
deque list map multimap multiset priority_queue set unordered_map unordered_multi_map unordered_multi_set unordered_set
Suggested resolution:
Provide a definition for each of the affected containers...
[ Bellevue: ]
Move to Open and ask Alisdair to provide wording.
[ 2009-07 Frankfurt: ]
Daniel to provide wording. N2590 is no longer applicable.
[ 2009-07-28 Daniel provided wording. ]
- It assumes that the proposed resolution for 883 is applied, which breaks the circularity of definition between member
swap
and freeswap
.- It uses the notation of the pre-concept allocator trait
allocator_propagation_map
, which might be renamed after the next refactoring phase of generalized allocators.- It requires that compare objects, key equal functions and hash functions in containers are swapped via unqualified free
swap
according to 594.
[ 2009-09-30 Daniel adds: ]
The outcome of this issue should be considered with the outcome of 1198 both in style and in content (e.g. bullet 9 suggests to define the semantic of
void priority_queue::swap(priority_queue&)
in terms of the memberswap
of the container).
[ 2009-10 Santa Cruz: ]
Looked at, but took no action on as it overlaps too much with N2982. Waiting for a new draft WP.
[ 2009-10 Santa Cruz: ]
Leave as open. Pablo to provide wording.
[ 2009-10-26 Pablo updated wording. Here is the wording he replaced: ]
Add a new Throws clause just after 99 [allocator.propagation.map]/5:
static void swap(Alloc& a, Alloc& b);Effects: [..]
Throws: Nothing.
[ This exception requirement is added, such that it's combination with the general container requirements of N2723 [container.requirements.general]/9 make it unambiguously clear that the following descriptions of "swaps the allocators" have the following meaning: (a) This swap is done by calling
allocator_propagation_map<allocator_type>::swap
and (b) This allocator swap does never propagate an exception ]Change 23.2.7.2 [associative.reqmts.except]/3 as indicated:
For associative containers, no
swap
function throws an exception unless that exception is thrown by thecopy constructor or copy assignment operatorswap
of the container'sPred
objects(if any).Change 23.2.8.2 [unord.req.except]/3 as indicated:
For unordered associative containers, no
swap
function throws an exception unless that exception is thrown by thecopy constructor or copy assignment operatorswap
of the container'sHash
orPred
objects, respectively(if any).Insert a new paragraph just after 23.3 [sequences]/1:
In addition to being available via inclusion of the
<algorithm>
header, theswap
function templates in 26.7.3 [alg.swap] are also available when the header<queue>
is included.[ There is a new issue in process that will suggest a minimum header for
swap
andmove
. If this one is provided, this text can be removed and the header dependency should be added to<queue>
]Add one further clause at the end of 23.3.3.4 [array.special]:
[This part is added, because otherwise
array::swap
would otherwise contradict the general contract of 23.2.2 [container.requirements.general] p. 10 b. 5]Throws: Nothing, unless one of the element-wise
swap
calls throws an exception.
In 23.3.5 [deque], class template
deque
synopsis change as indicated:void swap(deque<T,Alloc>&);At the end of 23.3.5.4 [deque.modifiers] add as indicated:
void swap(deque& x);Effects: Exchanges the contents and swaps the allocators of
*this
with that ofx
.Complexity: Constant time.
In [forwardlist], class template
forward_list
synopsis change as indicated:void swap(forward_list<T,Allocator>&);At the end of [forwardlist.modifiers] add as indicated:
void swap(forward_list& x);Effects: Exchanges the contents and swaps the allocators of
*this
with that ofx
.Complexity: Constant time.
In 23.3.9 [list], class template
list
synopsis change as indicated:void swap(list<T,Allocator>&);At the end of 23.3.9.4 [list.modifiers] add as indicated:
void swap(list& x);Effects: Exchanges the contents and swaps the allocators of
*this
with that ofx
.Complexity: Constant time.
At the end of 23.6.4.4 [priqueue.members] add a new prototype description:
void swap(priority_queue& q);Requires:
Compare
shall satisfy theSwappable
requirements ( [swappable]).[ This requirement is added to ensure that even a user defined
swap
which is found by ADL forCompare
satisfies theSwappable
requirements ]Effects:
this->c.swap(q.c); swap(this->comp, q.comp);
Throws: What and if
c.swap(q.c)
andswap(comp, q.comp)
throws.[ This part is added, because otherwise
priority_queue::swap
would otherwise contradict the general contract of 23.2.2 [container.requirements.general] p. 10 b. 5 ]
In 23.3.11 [vector], class template
vector
synopsis change as indicated:void swap(vector<T,Allocator>&);Change 23.3.11.3 [vector.capacity] p. 8 as indicated:
void swap(vector<T,Allocator>& x);Effects: Exchanges the contents and
capacity()
and swaps the allocators of*this
with that ofx
.Insert a new paragraph just before 23.4 [associative]/1:
In addition to being available via inclusion of the
<algorithm>
header, theswap
function templates in 26.7.3 [alg.swap] are also available when any of the headers<map>
or<set>
are included.
In 23.4.3 [map], class template
map
synopsis change as indicated:void swap(map<Key,T,Compare,Allocator>&);At the end of 23.4.3.4 [map.modifiers] add as indicated:
void swap(map& x);Requires: Compare shall satisfy the
Swappable
requirements ( [swappable]).[ This requirement is added to ensure that even a user defined
swap
which is found by ADL forCompare
satisfies theSwappable
requirements ]Effects: Exchanges the contents and swaps the allocators of
*this
with that ofx
, followed by an unqualifiedswap
of the comparison objects of*this
andx
.Complexity: Constant time
In 23.4.4 [multimap], class template
multimap
synopsis change as indicated:void swap(multimap<Key,T,Compare,Allocator>&);At the end of 23.4.4.3 [multimap.modifiers] add as indicated:
void swap(multimap& x);Requires: Compare shall satisfy the
Swappable
requirements ( [swappable]).Effects: Exchanges the contents and swaps the allocators of
*this
with that ofx
, followed by an unqualifiedswap
of the comparison objects of*this
andx
.Complexity: Constant time
In 23.4.6 [set], class template
set
synopsis change as indicated:void swap(set<Key,Compare,Allocator>&);After section 23.4.6.2 [set.cons] add a new section
set
modifiers 23.4.6.4 [set.modifiers] and add the following paragraphs:void swap(set& x);Requires: Compare shall satisfy the
Swappable
requirements ( [swappable]).Effects: Exchanges the contents and swaps the allocators of
*this
with that ofx
, followed by an unqualifiedswap
of the comparison objects of*this
andx
.Complexity: Constant time
In 23.4.7 [multiset], class template
multiset
synosis, change as indicated:void swap(multiset<Key,Compare,Allocator>&);After section 23.4.7.2 [multiset.cons] add a new section
multiset
modifiers [multiset.modifiers] and add the following paragraphs:void swap(multiset& x);Requires: Compare shall satisfy the
Swappable
requirements ( [swappable]).Effects: Exchanges the contents and swaps the allocators of
*this
with that ofx
, followed by an unqualifiedswap
of the comparison objects of*this
andx
.Complexity: Constant time
Insert a new paragraph just before 23.5 [unord] p. 1:
In addition to being available via inclusion of the
<algorithm>
header, theswap
function templates in 26.7.3 [alg.swap] are also available when any of the headers<unordered_map>
or<unordered_set>
are included.After section 23.5.3.3 [unord.map.elem] add a new section unordered_map modifiers 23.5.3.4 [unord.map.modifiers] and add the following paragraphs:
void swap(unordered_map& x);Requires:
Hash
andPred
shall satisfy theSwappable
requirements ( [swappable]).[ This requirement is added to ensure that even a user defined
swap
which is found by ADL forHash
andPred
satisfies theSwappable
requirements ]Effects: Exchanges the contents and hash policy and swaps the allocators of
*this
with that ofx
, followed by an unqualifiedswap
of thePred
objects and an unqualifiedswap
of theHash
objects of*this
andx
.Complexity: Constant time
After section 23.5.4.2 [unord.multimap.cnstr] add a new section unordered_multimap modifiers 23.5.4.3 [unord.multimap.modifiers] and add the following paragraphs:
void swap(unordered_multimap& x);Requires:
Hash
andPred
shall satisfy theSwappable
requirements ( [swappable]).Effects: Exchanges the contents and hash policy and swaps the allocators of
*this
with that ofx
, followed by an unqualifiedswap
of thePred
objects and an unqualifiedswap
of theHash
objects of*this
andx
Complexity: Constant time
After section 23.5.6.2 [unord.set.cnstr] add a new section unordered_set modifiers 23.5.6.4 [unord.set.modifiers] and add the following paragraphs:
void swap(unordered_set& x);Requires:
Hash
andPred
shall satisfy theSwappable
requirements ( [swappable]).Effects: Exchanges the contents and hash policy and swaps the allocators of
*this
with that ofx
, followed by an unqualifiedswap
of thePred
objects and an unqualifiedswap
of theHash
objects of*this
andx
Complexity: Constant time
After section 23.5.7.2 [unord.multiset.cnstr] add a new section unordered_multiset modifiers [unord.multiset.modifiers] and add the following paragraphs:
void swap(unordered_multiset& x);Requires:
Hash
andPred
shall satisfy theSwappable
requirements ( [swappable]).Effects: Exchanges the contents and hash policy and swaps the allocators of
*this
with that ofx
, followed by an unqualifiedswap
of thePred
objects and an unqualifiedswap
of theHash
objects of*this
andx
Complexity: Constant time
[ 2009-10-30 Pablo and Daniel updated wording. ]
[ 2010 Pittsburgh: Ready for Pittsburgh. ]
Proposed resolution:
[ This resolution is based on the September 2009 WP, N2960, except that it assumes that N2982 and issues 883 and 1232 have already been applied. Note in particular that Table 91 in N2960 is refered to as Table 90 because N2982 removed the old Table 90. This resolution also addresses issue 431. ]
In 23.2.2 [container.requirements.general], replace the a.swap(b) row in table 90, "container requirements" (was table 91 before the application of N2982 to the WP):
a.swap(b)
void
swap(a,b)Exchange the contents ofa
andb
.(Note A) swap(a,b)
void
a.swap(b)
(Note A)
Modify the notes immediately following Table 90 in 23.2.2 [container.requirements.general] as follows (The wording below is after the application of N2982 to N2960. The editor might also want to combine Notes A and B into one.):
Notes: the algorithms
swap(),equal() and lexicographical_compare() are defined in Clause 25. Those entries marked "(Note A)" or "(Note B)"shouldhave linear complexity for array and constant complexity for all other standard containers.
In 23.2.2 [container.requirements.general], before paragraph 8, add:
The expression
a.swap(b)
, for containersa
andb
of a standard container type other thanarray
, exchanges the values ofa
andb
without invoking any move, copy, or swap operations on the individual container elements. AnyCompare
,Pred
, orHash
function objects belonging toa
andb
shall beswappable
and are exchanged by unqualified calls to non-memberswap
. Ifallocator_traits<allocator_type>::propagate_on_container_swap::value == true
, then the allocators ofa
andb
are also exchanged using an unqualified call to non-memberswap
. Otherwise, the behavior is undefined unlessa.get_allocator() == b.get_allocator()
. Each iterator refering to an element in one container before the swap shall refer to the same element in the other container after the swap. It is unspecified whether an iterator with valuea.end()
before the swap will have valueb.end()
after the swap. In addition to being available via inclusion of the<utility>
header, theswap
function template in 26.7.3 [alg.swap] is also available within the definition of every standard container'sswap
function.
[ Note to the editor: Paragraph 2 starts with a sentence fragment, clearly from an editing or source-control error. ]
Modify 23.2.7.2 [associative.reqmts.except] as follows:
23.2.4.1 Exception safety guarantees 23.2.7.2 [associative.reqmts.except]
For associative containers, no
clear()
function throws an exception.erase(k)
does not throw an exception unless that exception is thrown by the container'sobject (if any).
PredCompareFor associative containers, if an exception is thrown by any operation from within an
insert()
function inserting a single element, theinsert()
function has no effect.For associative containers, no
swap
function throws an exception unless that exception is thrown by thecopy constructor or copy assignment operatorswap of the container'sobject (if any).
PredCompare
Modify 23.2.8.2 [unord.req.except], paragraph 3 as follows:
For unordered associative containers, no
swap
function throws an exception unless that exception is thrown by thecopy constructor or copy assignment operatorswap of the container'sHash
orPred
object (if any).
Modify section 23.3.3.4 [array.special]:
array specialized algorithms 23.3.3.4 [array.special]
template <class T, size_t N> void swap(array<T,N>& x,array<T,N>& y);
Effects:
swap_ranges(x.begin(), x.end(), y.begin() );x.swap(y);
Add a new section after [array.fill] (Note to the editor: array::fill make use of a concept requirement that must be removed or changed to text.):
array::swap [array.swap]
void swap(array& y);
Effects:
swap_ranges(this->begin(), this->end(), y.begin() );
Throws: Nothing unless one of the element-wise swap calls throws an exception.
[Note: Unlike other containers'
swap
functions,array::swap
takes linear, not constant, time, may exit via an exception, and does not cause iterators to become associated with the other container. — end note]
Insert a new paragraph just after 23.6 [container.adaptors]/1:
For container adaptors, no
swap
function throws an exception unless that exception is thrown by the swap of the adaptor'sContainer
orCompare
object (if any).