This paper serves as a supplement to LWG issue 941, Ref-qualifiers for assignment operators. The paper presents a proposed resolution to this issue, adding a ref-qualifier to over 200 assignment operators specified by the Committee Draft, N2800 [1]. The issue has been discussed before at comp.std.c++, December 2008, Ref-qualifiers for assignment operators in the Standard Library?.
if ( func() = value ) // Typical typo: == intended!
Built-in types don't support assignment to an rvalue, but unfortunately, a lot of types provided by the Standard Library do.
Fortunately the language now offers a syntax to prevent calling a certain member function on an rvalue: by adding a ref-qualifier (&) to the member function declaration (N2439, [2]). The operator= is explicitly mentioned as a use case of ref-qualifiers, in the section "Examples" of "Extending Move Semantics To *this (Revision 1)", by Daveed Vandevoorde and Bronek Kozicki (N1821, [3]). Bronek Kozicki also presented an example, showing that it would be beneficial to disable assignment to an rvalue within a generic context, in another paper, N1784 [4].
This paper proposes adding & ref-qualifiers to all the appropriate assignment operators in the library.
There are only a few very specific types for which it makes sense to support assigning to an rvalue. In particular, types that serve as a proxy, e.g., vector<bool>::reference, and types whose assignment operators are const-qualified (e.g., slice_array). Those types are of course excluded from this proposal.
Note that there is also a historical reason to support this proposal, as the term "lvalue" originally comes from being allowed as the left operand of an assignment (C Standard [5], footnote 53).
12.8 [class.copy]/10 specifies that an implicitly-declared copy assignment operator has one of the following two forms (depending on the definition of the class X):
X& X::operator=(const X&)
X& X::operator=(X&)
The library has over 150 classes and class templates that have an implicitly-declared copy assignment operator. Subsection Proposed explicitly-defaulted copy-assignment operators proposes to add an & ref-qualified copy assignment operator to those library types. Note that this subsection might interact with CWG issue 733, Reference qualification of copy assignment operators, submitted by Alberto Ganesh Barbati.
For an associated member function (or member function template) in a type X (after substitution of the concept map arguments into the associated member function or member function template), let x be an object of type cv X, where cv are the cv-qualifiers on the associated member function (or member function template). If the requirement has no ref-qualifier or if its ref-qualifier is &, x is an lvalue;
Note that Sebastian Gesemann and Douglas Gregor have been discussing the interaction between ref-qualifiers and concepts at comp.std.c++, January 2009, C++0x concepts and ref qualifiers inconsistency
template <typename T> T& make_lvalue(T&& arg) { return arg; }For example, the following would assign a literal, "text", to a temporary std::string, even when the assignment operators of std::string would have an & ref-qualifier:
make_lvalue( std::string() ) = "text";So the expressive power of the library will not be significantly reduced by adding & ref-qualifiers.
We believe that:#include <iostream> #include <vector> class my_proxy { int* i_; public: explicit my_proxy(int& i) : i_(&i) {} my_proxy& operator=(const my_proxy& i) { *i_ = *i.i_; return *this; } my_proxy& operator=(int i) { *i_ = i; return *this; } operator int() const {return *i_;} }; std::vector<my_proxy> tie(int& i, int& j, int& k) { std::vector<my_proxy> v; v.push_back(my_proxy(i)); v.push_back(my_proxy(j)); v.push_back(my_proxy(k)); return v; } int main() { std::vector<my_proxy> v; int i = 1; int j = 2; int k = 3; int l = 4; int m = 5; int n = 6; v.push_back(my_proxy(l)); v.push_back(my_proxy(m)); v.push_back(my_proxy(n)); std::cout << "i = " << i << '\n'; std::cout << "j = " << j << '\n'; std::cout << "k = " << k << '\n'; tie(i, j, k) = v; std::cout << "i = " << i << '\n'; std::cout << "j = " << j << '\n'; std::cout << "k = " << k << '\n'; }
Note that the original example is based on a library implementation specific assumption, being that the copy-assignment operator of vector does an element-wise assignment, when its lhs and its rhs have the same size. assign_proxy does not make such an assumption, as it uses std::copy instead, therefore the proxy was actually needed to fix a weakness of the original example.template<typename T> class assign_proxy { private: T value; public: assign_proxy(const T& value) : value(value) {} assign_proxy(T&& value) : value( std::move(value) ) {} assign_proxy& operator=(const T& value) && { // Assumes that this->value has as many elements as value. std::copy(value.begin(), value.end(), this->value.begin()); return *this; } }; assign_proxy<std::vector<my_proxy>> tie(int& i, int& j, int& k) { std::vector<my_proxy> v; v.push_back(my_proxy(i)); v.push_back(my_proxy(j)); v.push_back(my_proxy(k)); return std::move(v); }
Note also that assign_proxy itself is not a part of the proposal.
The proposed resolution to LWG issue 941 adds a ref-qualifier to most of the assignment operators provided by the library. It proposed to add a single ampersand (&) to over 200 places within the Committee Draft [1], according to Table 1. Note that it also has fixes of two apparent typographical errors, in 23.2.3 [forwardlist] and 24.4.1.1 [reverse.iterator] regarding the return type of operator=. The proposed resolution also includes a subsection, Proposed changes to requirements, and a subsection Proposed explicitly-defaulted copy-assignment operators.
Table 1. Proposed changes to user-declared assignment operatorsSection | Line |
Contents | 56 operator=(const basic_string<charT, traits, Allocator>&) & effects . . . . . . . . . . . . . 667 |
Contents | 57 operator=(const basic_string<charT, traits, Allocator>&&) & effects . . . . . . . . . . . . 667 |
18.5.2.1 [bad.alloc] | bad_alloc& operator=(const bad_alloc&) & throw(); |
18.5.2.1 [bad.alloc]/3 | bad_alloc& operator=(const bad_alloc&) & throw(); |
18.6.3 [bad.cast] | bad_cast& operator=(const bad_cast&) & throw(); |
18.6.3 [bad.cast]/3 | bad_cast& operator=(const bad_cast&) & throw(); |
18.6.4 [bad.typeid] | bad_typeid& operator=(const bad_typeid&) & throw(); |
18.6.4 [bad.typeid]/3 | bad_typeid& operator=(const bad_typeid&) & throw(); |
18.7.1 [exception] | exception& operator=(const exception&) & throw(); |
18.7.1 [exception]/3 | exception& operator=(const exception&) & throw(); |
18.7.2.1 [bad.exception] | bad_exception& operator=(const bad_exception&) & throw(); |
18.7.2.1 [bad.exception]/3 | bad_exception& operator=(const bad_exception&) & throw(); |
18.7.6 [except.nested] | nested_exception& operator=(const nested_exception&) & throw() = default; |
19.4.2.2 [syserr.errcode.overview] | error_code& operator=(E e) &; |
19.4.2.4 [syserr.errcode.modifiers] | error_code& operator=(E e) &; |
19.4.3.2 [syserr.errcondition.overview] | error_condition& operator=(E e) &; |
19.4.3.4 [syserr.errcondition.modifiers] | error_condition& operator=(E e) &; |
20.2.3 [pairs]/1 | pair& operator=(const pair<U , V>& p) &; |
20.2.3 [pairs]/1 | requires MoveAssignable<T1> && MoveAssignable<T2> pair& operator=(pair&& p) &; |
20.2.3 [pairs]/1 | pair& operator=(pair<U , V>&& p) &; |
20.2.3 [pairs]/10 | pair& operator=(const pair<U , V>& p) &; |
20.2.3 [pairs]/12 | requires MoveAssignable<T1> && MoveAssignable<T2> pair& operator=(pair&& p) &; |
20.2.3 [pairs]/14 | pair& operator=(pair<U, V>&& p) &; |
20.6.5 [refwrap] | reference_wrapper& operator=(const reference_wrapper<T>& x) &; |
20.6.5.2 [refwrap.assign] | reference_wrapper& operator=(const reference_wrapper<T>& x) &; |
20.6.16.2 [func.wrap.func] | function& operator=(const function&) &; |
20.6.16.2 [func.wrap.func] | function& operator=(function&&) &; |
20.6.16.2 [func.wrap.func] | function& operator=(nullptr_t) &; |
20.6.16.2 [func.wrap.func] | function& operator=(F) &; |
20.6.16.2 [func.wrap.func] | function& operator=(F&&) &; |
20.6.16.2 [func.wrap.func] | function& operator=(reference_wrapper<F>) &; |
20.6.16.2.1 [func.wrap.func.con] | function& operator=(const function& f) &; |
20.6.16.2.1 [func.wrap.func.con] | function& operator=(function&& f) &; |
20.6.16.2.1 [func.wrap.func.con] | function& operator=(nullptr_t) &; |
20.6.16.2.1 [func.wrap.func.con] | operator=(F f) &; |
20.6.16.2.1 [func.wrap.func.con] | function& operator=(F&& f) &; |
20.6.16.2.1 [func.wrap.func.con] | function& operator=(reference_wrapper<F> f) &; |
20.6.18 [func.referenceclosure] | reference_closure& operator=(const reference_closure&) & = default; |
20.6.18 [func.referenceclosure] | reference_closure& operator=(nullptr_t) &; |
20.6.18.1 [func.referenceclosure.cons] | reference_closure& operator=(const reference_closure& f) & |
20.6.18.1 [func.referenceclosure.cons] | reference_closure& operator=(nullptr_t) &; |
20.7.8 [storage.iterator]/1 | raw_storage_iterator<OutputIterator,T>& operator=(const T& element) &; |
20.7.8 [storage.iterator]/3 | raw_storage_iterator<OutputIterator,T>& operator=(const T& element) &; |
20.7.12.2 [unique.ptr.single] | unique_ptr& operator=(unique_ptr&& u) &; |
20.7.12.2 [unique.ptr.single] | template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) &; |
20.7.12.2 [unique.ptr.single] | unique_ptr& operator=(unspecified-pointer-type) &; |
20.7.12.2.3 [unique.ptr.single.asgn] | unique_ptr& operator=(unique_ptr&& u) &; |
20.7.12.2.3 [unique.ptr.single.asgn] | template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) &; |
20.7.12.2.3 [unique.ptr.single.asgn] | unique_ptr& operator=(unspecified-pointer-type) &; |
20.7.12.3 [unique.ptr.runtime] | unique_ptr& operator=(unique_ptr&& u) &; |
20.7.12.3 [unique.ptr.runtime] | unique_ptr& operator=(unspecified-pointer-type) &; |
20.7.13.2 [util.smartptr.shared] | shared_ptr& operator=(const shared_ptr& r) &; |
20.7.13.2 [util.smartptr.shared] | template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) &; |
20.7.13.2 [util.smartptr.shared] | shared_ptr& operator=(shared_ptr&& r) &; |
20.7.13.2 [util.smartptr.shared] | template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r) &; |
20.7.13.2 [util.smartptr.shared] | template<class Y> shared_ptr& operator=(auto_ptr<Y>&& r) &; |
20.7.13.2 [util.smartptr.shared] | template <class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r) &; |
20.7.13.2.3 [util.smartptr.shared.assign] | shared_ptr& operator=(const shared_ptr& r) &; |
20.7.13.2.3 [util.smartptr.shared.assign] | template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) &; |
20.7.13.2.3 [util.smartptr.shared.assign] | template<class Y> shared_ptr& operator=(auto_ptr<Y>&& r) &; |
20.7.13.2.3 [util.smartptr.shared.assign] | shared_ptr& operator=(shared_ptr&& r) &; |
20.7.13.2.3 [util.smartptr.shared.assign] | template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r) &; |
20.7.13.2.3 [util.smartptr.shared.assign] | template <class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r) &; |
20.7.13.3 [util.smartptr.weak] | weak_ptr& operator=(weak_ptr const& r) &; |
20.7.13.3 [util.smartptr.weak] | template<class Y> weak_ptr& operator=(weak_ptr<Y> const& r) &; |
20.7.13.3 [util.smartptr.weak] | template<class Y> weak_ptr& operator=(shared_ptr<Y> const& r) &; |
20.7.13.3.3 [util.smartptr.weak.assign] | weak_ptr& operator=(const weak_ptr& r) &; |
20.7.13.3.3 [util.smartptr.weak.assign] | template<class Y> weak_ptr& operator=(const weak_ptr<Y>& r) &; |
20.7.13.3.3 [util.smartptr.weak.assign] | template<class Y> weak_ptr& operator=(const shared_ptr<Y>& r) &; |
20.7.13.5 [util.smartptr.enab] | enable_shared_from_this& operator=(enable_shared_from_this const&) &; |
20.7.13.5 [util.smartptr.enab] | enable_shared_from_this<T>& operator=(const enable_shared_from_this<T>&) &; |
20.7.13.5 [util.smartptr.enab] | enable_shared_from_this& operator=(enable_shared_from_this const &) & { return *this; } |
20.8.3 [time.duration] | duration& operator=(const duration&) & = default; |
21.3 [basic.string] | basic_string& operator=(const basic_string& str) &; |
21.3 [basic.string] | basic_string& operator=(basic_string&& str) &; |
21.3 [basic.string] | basic_string& operator=(const charT* s) &; |
21.3 [basic.string] | basic_string& operator=(charT c) &; |
21.3 [basic.string] | basic_string& operator=(initializer_list<charT>) &; |
21.3.2 [string.cons] | operator=(const basic_string<charT,traits,Allocator>& str) &; |
21.3.2 [string.cons] | Table 56 — operator=(const basic_string<charT, traits, Allocator>&) & effects |
21.3.2 [string.cons] | operator=(const basic_string<charT,traits,Allocator>&& str) &; |
21.3.2 [string.cons] | Table 57 — operator=(const basic_string<charT, traits, Allocator>&&) & effects |
21.3.2 [string.cons] | operator=(const charT* s) &; |
21.3.2 [string.cons] | basic_string<charT,traits,Allocator>& operator=(charT c) &; |
21.3.2 [string.cons] | basic_string& operator=(initializer_list<charT> il) &; |
22.1.1 [locale] | const locale& operator=(const locale& other) & throw(); |
22.1.1.2 [locale.cons] | const locale& operator=(const locale& other) & throw(); |
23.2.2 [deque] | deque<T,Alloc>& operator=(const deque<T,Alloc>& x) &; |
23.2.2 [deque] | deque<T,Alloc>& operator=( deque<T,Alloc>&& x) &; |
23.2.2 [deque] | deque& operator=(initializer_list<T>) &; |
23.2.3 [forwardlist] | forward_list<T,Alloc>& operator=(const forward_list<T,Alloc>& x) &; |
23.2.3 [forwardlist] | forward_list<T,Alloc>& operator=(forward_list<T,Alloc>&& x) &; |
23.2.3 [forwardlist] | forward_list<T,Alloc>& operator=(initializer_list<T>) &; |
23.2.4 [list] | list<T,Alloc>& operator=(const list<T,Alloc>& x) &; |
23.2.4 [list] | list<T,Alloc>& operator=(list<T,Alloc>&& x) &; |
23.2.4 [list] | list<T,Alloc>& operator=(initializer_list<T>) &; |
23.2.5.1.1 [queue.defn] | requires MoveAssignable<Cont> queue& operator=(queue&& q) & |
23.2.5.2 [priority.queue] | requires MoveAssignable<Cont> priority_queue& operator=(priority_queue&&) &; |
23.2.6 [vector] | vector<T,Alloc>& operator=(const vector<T,Alloc>& x) &; |
23.2.6 [vector] | vector<T,Alloc>& operator=(vector<T,Alloc>&& x) &; |
23.2.6 [vector] | vector<T,Alloc>& operator=(initializer_list<T>) &; |
23.2.7 [vector.bool] | vector<bool,Alloc>& operator=(const vector<bool,Alloc>& x) &; |
23.2.7 [vector.bool] | vector<bool,Alloc>& operator=(vector<bool,Alloc>&& x) &; |
23.2.7 [vector.bool] | vector<bool,Alloc>& operator=(initializer_list<bool>) &; |
23.3.1 [map] | map<Key,T,Compare,Alloc>& operator=(const map<Key,T,Compare,Alloc>& x) &; |
23.3.1 [map] | operator=(map<Key,T,Compare,Alloc>&& x) &; |
23.3.1 [map] | map<Key,T,Compare,Alloc>& operator=(initializer_list<value_type>) &; |
23.3.2 [multimap] | multimap<Key,T,Compare,Alloc>& operator=(const multimap<Key,T,Compare,Alloc>& x) &; |
23.3.2 [multimap] | operator=(const multimap<Key,T,Compare,Alloc>&& x) &; |
23.3.2 [multimap] | multimap<Key,T,Compare,Alloc>& operator=(initializer_list<value_type>) &; |
23.3.3 [set] | set<Key,Compare,Alloc>& operator=(const set<Key,Compare,Alloc>& x) &; |
23.3.3 [set] | set<Key,Compare,Alloc>& operator=(set<Key,Compare,Alloc>&& x) &; |
23.3.3 [set] | set<Key,Compare,Alloc>& operator=(initializer_list<value_type>) &; |
23.3.4 [multiset] | multiset<Key,Compare,Alloc>& operator=(const multiset<Key,Compare,Alloc>& x) &; |
23.3.4 [multiset] | multiset<Key,Compare,Alloc>& operator=(multiset<Key,Compare,Alloc>&& x) &; |
23.3.4 [multiset] | multiset<Key,Compare,Alloc>& operator=(initializer_list<value_type>) &; |
23.4.1 [unord.map] | unordered_map& operator=(const unordered_map&) &; |
23.4.1 [unord.map] | unordered_map& operator=(unordered_map&&) &; |
23.4.1 [unord.map] | unordered_map& operator=(initializer_list<value_type>) &; |
23.4.2 [unord.multimap] | unordered_multimap& operator=(const unordered_multimap&) &; |
23.4.2 [unord.multimap] | unordered_multimap& operator=(unordered_multimap&&) &; |
23.4.2 [unord.multimap] | unordered_multimap& operator=(initializer_list<value_type>) &; |
23.4.3 [unord.set] | unordered_set& operator=(const unordered_set&) &; |
23.4.3 [unord.set] | unordered_set& operator=(unordered_set&&) &; |
23.4.3 [unord.set] | unordered_set& operator=(initializer_list<value_type>) &; |
23.4.4 [unord.multiset] | unordered_multiset& operator=(const unordered_multiset&) &; |
23.4.4 [unord.multiset] | unordered_multiset& operator=(unordered_multiset&&) &; |
23.4.4 [unord.multiset] | unordered_multiset& operator=(initializer_list<value_type>) &; |
24.4.1.1 [reverse.iterator] | reverse_iterator& operator=(const reverse_iterator<U>& u) &; |
24.4.1.2.2 [reverse.iter.op=] | operator=(const reverse_iterator<U>& u) &; |
24.4.2 [insert.iterators] | operator* returns the insert iterator itself. The assignment operator=(const T& x) & is defined on insert iterators |
24.4.2.1 [back.insert.iterator] | operator=(const Cont::value_type& value) &; |
24.4.2.1 [back.insert.iterator] | operator=(Cont::value_type&& value) &; |
24.4.2.2.2 [back.insert.iter.op=] | operator=(const Cont::value_type& value) &; |
24.4.2.2.2 [back.insert.iter.op=] | operator=(Cont::value_type&& value) &; |
24.4.2.3 [front.insert.iterator] | operator=(const Cont::value_type& value) &; |
24.4.2.3 [front.insert.iterator] | operator=(Cont::value_type&& value) &; |
24.4.2.4.2 [front.insert.iter.op=] | operator=(const Cont::value_type& value) &; |
24.4.2.4.2 [front.insert.iter.op=] | operator=(Cont::value_type&& value) &; |
24.4.2.5 [insert.iterator] | operator=(const Cont::value_type& value) &; |
24.4.2.5 [insert.iterator] | operator=(Cont::value_type&& value) &; |
24.4.2.6.2 [insert.iter.op=] | operator=(const Cont::value_type& value) &; |
24.4.2.6.2 [insert.iter.op=] | operator=(Cont::value_type&& value) &; |
24.4.3.1 [move.iterator] | move_iterator& operator=(const move_iterator<U>& u) &; |
24.4.3.2.2 [move.iter.op=] | move_iterator& operator=(const move_iterator<U>& u) &; |
24.5.2 [ostream.iterator] | ostream_iterator<T,charT,traits>& operator=(const T& value) &; |
24.5.2.2 [ostream.iterator.ops] | ostream_iterator& operator=(const T& value) &; |
24.5.4 [ostreambuf.iterator] | ostreambuf_iterator& operator=(charT c) &; |
24.5.4.2 [ostreambuf.iter.ops] | operator=(charT c) &; |
26.1 [numeric.requirements] | If T is a class, it has a public assignment operator whose signature is either T& T::operator=(const T&) or T& T::operator=(T); this assignment operator may have an & ref-qualifier; |
26.3.2 [complex] | complex<T>& operator= (const T&) &; |
26.3.2 [complex] | complex& operator=(const complex&) &; |
26.3.2 [complex] | template<class X> complex<T>& operator= (const complex<X>&) &; |
26.3.3 [complex.special] | complex<float>& operator= (float) &; |
26.3.3 [complex.special] | complex<float>& operator=(const complex<float>&) &; |
26.3.3 [complex.special] | template<class X> complex<float>& operator= (const complex<X>&) &; |
26.3.3 [complex.special] | complex<double>& operator= (double) &; |
26.3.3 [complex.special] | complex<double>& operator=(const complex<double>&) &; |
26.3.3 [complex.special] | template<class X> complex<double>& operator= (const complex<X>&) &; |
26.3.3 [complex.special] | complex<long double>& operator=(const complex<long double>&) &; |
26.3.3 [complex.special] | complex<long double>& operator= (long double) &; |
26.3.3 [complex.special] | template<class X> complex<long double>& operator= (const complex<X>&) &; |
26.5.2 [template.valarray] | valarray<T>& operator=(const valarray<T>&) &; |
26.5.2 [template.valarray] | valarray<T>& operator=(valarray<T>&&) &; |
26.5.2 [template.valarray] | valarray& operator=(initializer_list<T>) &; |
26.5.2 [template.valarray] | valarray<T>& operator=(const T&) &; |
26.5.2 [template.valarray] | valarray<T>& operator=(const slice_array<T>&) &; |
26.5.2 [template.valarray] | valarray<T>& operator=(const gslice_array<T>&) &; |
26.5.2 [template.valarray] | valarray<T>& operator=(const mask_array<T>&) &; |
26.5.2 [template.valarray] | valarray<T>& operator=(const indirect_array<T>&) &; |
26.5.2.2 [valarray.assign] | valarray<T>& operator=(const valarray<T>&) &; |
26.5.2.2 [valarray.assign] | valarray<T>& operator=(valarray<T>&& v) &; |
26.5.2.2 [valarray.assign] | valarray& operator=(initializer_list<T> il) &; |
26.5.2.2 [valarray.assign] | valarray<T>& operator=(const T&) &; |
26.5.2.2 [valarray.assign] | valarray<T>& operator=(const slice_array<T>&) &; |
26.5.2.2 [valarray.assign] | valarray<T>& operator=(const gslice_array<T>&) &; |
26.5.2.2 [valarray.assign] | valarray<T>& operator=(const mask_array<T>&) &; |
26.5.2.2 [valarray.assign] | valarray<T>& operator=(const indirect_array<T>&) &; |
27.5.2 [streambuf] | basic_streambuf& operator=(const basic_streambuf& rhs) &; |
27.5.2.3.1 [streambuf.assign] | basic_streambuf& operator=(const basic_streambuf& rhs) &; |
27.6.1.1 [istream] | basic_istream& operator=(basic_istream&& rhs) &; |
27.6.1.1.2 [istream.assign] | basic_istream& operator=(basic_istream&& rhs) &; |
27.6.1.5 [iostreamclass] | basic_iostream& operator=(basic_iostream&& rhs) &; |
27.6.1.5.3 [iostream.assign] | basic_iostream& operator=(basic_iostream&& rhs) &; |
27.6.2.1 [ostream] | basic_ostream& operator=(basic_ostream&& rhs) &; |
27.6.2.3 [ostream.assign] | basic_ostream& operator=(basic_ostream&& rhs) &; |
27.7.1 [stringbuf] | basic_stringbuf& operator=(basic_stringbuf&& rhs) &; |
27.7.1.2 [stringbuf.assign] | basic_stringbuf& operator=(basic_stringbuf&& rhs) &; |
27.7.2 [istringstream] | basic_istringstream& operator=(basic_istringstream&& rhs) &; |
27.7.2.2 [istringstream.assign] | basic_istringstream& operator=(basic_istringstream&& rhs) &; |
27.7.3 [ostringstream] | basic_ostringstream& operator=(basic_ostringstream&& rhs) &; |
27.7.3.2 [ostringstream.assign] | basic_ostringstream& operator=(basic_ostringstream&& rhs) &; |
27.7.4 [stringstream] | basic_stringstream& operator=(basic_stringstream&& rhs) &; |
27.7.5.1 [stringstream.assign] | basic_stringstream& operator=(basic_stringstream&& rhs) &; |
27.8.1.1 [filebuf] | basic_filebuf& operator=(basic_filebuf&& rhs) &; |
27.8.1.3 [filebuf.assign] | basic_filebuf& operator=(basic_filebuf&& rhs) &; |
27.8.1.6 [ifstream] | basic_ifstream& operator=(basic_ifstream&& rhs) &; |
27.8.1.8 [ifstream.assign] | basic_ifstream& operator=(basic_ifstream&& rhs) &; |
27.8.1.10 [ofstream] | basic_ofstream& operator=(basic_ofstream&& rhs) &; |
27.8.1.12 [ofstream.assign] | basic_ofstream& operator=(basic_ofstream&& rhs) &; |
27.8.1.14 [fstream] | basic_fstream& operator=(basic_fstream&& rhs) &; |
27.8.1.16 [fstream.assign] | basic_fstream& operator=(basic_fstream&& rhs) &; |
28.8 [re.regex] | basic_regex& operator=(const basic_regex&) &; |
28.8 [re.regex] | basic_regex& operator=(const charT* ptr) &; |
28.8 [re.regex] | basic_regex& operator=(const basic_string<charT, ST, SA>& p) &; |
28.8.2 [re.regex.construct] | basic_regex& operator=(const basic_regex& e) &; |
28.8.2 [re.regex.construct] | basic_regex& operator=(const charT* ptr) &; |
28.8.2 [re.regex.construct] | basic_regex& operator=(const basic_string<charT, ST, SA>& p) &; |
28.10 [re.results] | match_results& operator=(const match_results& m) &; |
28.10.1 [re.results.const] | match_results& operator=(const match_results& m) &; |
28.12.1 [re.regiter] | regex_iterator& operator=(const regex_iterator&) &; |
28.12.2 [re.tokiter] | regex_token_iterator& operator=(const regex_token_iterator&) &; |
29.3.1 [atomics.types.integral] | bool operator=(bool) volatile &; |
29.3.1 [atomics.types.integral] | integral operator=(integral) volatile &; |
29.3.2 [atomics.types.address] | void* operator=(void*) volatile &; |
29.3.3 [atomics.types.generic] | T operator=(T) volatile &; |
29.3.3 [atomics.types.generic] | integral operator=(integral) volatile &; |
29.3.3 [atomics.types.generic] | T* operator=(T*) volatile &; |
29.4 [atomics.types.operations] | C A::operator=(C desired) volatile &; |
30.2.1 [thread.thread.class] | thread& operator=(thread&&) &; |
30.2.1.4 [thread.thread.assign] | thread& operator=(thread&& x) &; |
30.3.3.2 [thread.lock.unique] | unique_lock& operator=(unique_lock&& u) &; |
30.3.3.2.1 [thread.lock.unique.cons] | unique_lock& operator=(unique_lock&& u) &; |
30.5.6 [futures.promise] | promise & operator=(promise&& rhs) &; |
30.5.6 [futures.promise] | promise& operator=(promise&& rhs) &; |
30.5.8 [futures.task] | packaged_task& operator=(packaged_task&& other) &; |
30.5.8 [futures.task]/6 | packaged_task& operator=(packaged_task&& other) &; |
Change 23.1.1 [container.requirements.general]/4:
In Tables 80 and 81, X denotes a container class containing objects of type T, a and b denote values of type X, u denotes an identifier,r denotes an lvalue or a const rvalue of type X,lv denotes a non-const lvalue of type X, and rv denotes a non-const rvalue of type X.
Change Table 80:
Table 80 - Container requirements Expression Return type Operational
semanticsAssertion/note
pre-/post-conditionComplexity alv = rv;X& All existing elements
ofalv are either move
assigned or destroyedalv shall be equal to
the value that rv
had before this constructionlinear ... ... ... ... ... rlv = aX& post: rlv == a.linear
Change 23.1.3 [sequence.reqmts]/3:
In Tables 83 and 84, X denotes a sequence container class, a denotes a value of X containing elements of type T, lv denotes a non-const lvalue of type X, ...
Change Table 83:
Table 83 - Sequence container requirements (in addition to container) Expression Return type Assertion/note
pre-/post-conditionalv = ilX& alv = X(il);
return *this;
Change 23.1.4 [associative.reqmts]/7:
In Table 85 ...r denotes an lvalue or a const rvalue of type X,lv denotes a non-const lvalue of type X, rv denotes a non-const rvalue of type X, ...
Change Table 85: [The proposed change for a.emplace_hint() is an obvious editorial fix]
Table 85 - Associative container requirements (in addition to container) Expression Return type Assertion/note
pre-/post-conditionComplexity alv = ilX& alv = X(il);
return *this;... ... ... ... ... a.emplace_-
hint(p,args)iterator ... logarithmic in general, but
amortized constant if the
element is inserted right afterrp
Change 23.1.5 [unord.req]/9:
In table 87: X is an unordered associative container class, a is an object of type X, lv denotes a non-const lvalue of type X, ...
Change Table 87: [The proposed change for the return type is an obvious editorial fix]
Table 87 - Unordered associative container requirements (in addition to container) Expression Return type Assertion/note
pre-/post-conditionComplexity alv = bX& ... ...
Change 27.4.3.2 [fpos.operations]/1:
Operations specified in Table 105 are permitted: In that table, ... - t refers to a non-const lvalue of type P, ...
Change Table 105:
Table 105 - Position type requirements Expression Return type Operational
semanticAssertion/note
pre-/post-conditionqt = p + o
p += ofpos + offset qt - o == pqt = p - o
p -= ofpos - offset qt + o == p
This subsection proposes to add a user-declared copy-assignment operator, having an & ref-qualifier, and an explicitly-defaulted definition, to each of the library class types and class templates that currently have an implicitly declared copy-assignment operator. The proposed changes are listed at Table 2.
Table 2. Proposed changes for class definitions with implicit assignment operators
Section | Class (Template) | Added Line to Class Body |
18.2.1.1 [numeric.limits] | class template numeric_limits | numeric_limits& operator=(const numeric_limits&) & = default; |
18.2.1.5 [numeric.special]/2+3 | template<> class numeric_limits<float> template<> class numeric_limits<bool> | numeric_limits& operator=(const numeric_limits&) & = default; |
18.5 [support.dynamic]/1 | struct nothrow_t | nothrow_t& operator=(const nothrow_t&) & = default; |
18.6 [support.rtti]/1 | template<> class hash<type_index> | hash& operator=(const hash&) & = default; |
18.6.2.1 [type.index.overview] | class type_index | type_index& operator=(const type_index&) & = default; |
18.8 [support.initlist]/1 | class template initializer_list | initializer_list& operator=(const initializer_list&) & = default; |
19.1.1 [logic.error] | class logic_error | logic_error& operator=(const logic_error&) & = default; |
19.1.2 [domain.error] | class domain_error | domain_error& operator=(const domain_error&) & = default; |
19.1.3 [invalid.argument] | class invalid_argument | invalid_argument& operator=(const invalid_argument&) & = default; |
19.1.4 [length.error] | class length_error | length_error& operator=(const length_error&) & = default; |
19.1.5 [out.of.range] | class out_of_range | out_of_range& operator=(const out_of_range&) & = default; |
19.1.6 [runtime.error] | class runtime_error | runtime_error& operator=(const runtime_error&) & = default; |
19.1.7 [range.error] | class range_error | range_error& operator=(const range_error&) & = default; |
19.1.8 [overflow.error] | class overflow_error | overflow_error& operator=(const overflow_error&) & = default; |
19.1.9 [underflow.error] | class underflow_error | underflow_error& operator=(const underflow_error&) & = default; |
19.4.2.2 [syserr.errcode.overview]/1 | class error_code | error_code& operator=(const error_code&) & = default; |
19.4.3.2 [syserr.errcondition.overview]/1 | class error_condition | error_condition& operator=(const error_condition&) & = default; |
19.4.5.1 [syserr.syserr.overview]/2 | class system_error | system_error& operator=(const system_error&) & = default; |
20.2.6 [template.bitset]/1 | class template bitset | bitset& operator=(const bitset&) & = default; |
20.3.1 [ratio.ratio] | class template ratio | ratio& operator=(const ratio&) & = default; |
20.3.2 [ratio.arithmetic] | class template ratio_add class template ratio_subtract class template ratio_multiply class template ratio_divide |
ratio_add& operator=(const ratio_add&) & = default; ratio_subtract& operator=(const ratio_subtract&) & = default; ratio_multiply& operator=(const ratio_multiply&) & = default; ratio_divide& operator=(const ratio_divide&) & = default; |
20.3.3 [ratio.comparison] | class template ratio_equal class template ratio_not_equal class template ratio_less class template ratio_less_equal class template ratio_greater class template ratio_greater_equal |
ratio_equal& operator=(const ratio_equal&) & = default; ratio_not_equal& operator=(const ratio_not_equal&) & = default; ratio_less& operator=(const ratio_less&) & = default; ratio_less_equal& operator=(const ratio_less_equal&) & = default; ratio_greater& operator=(const ratio_greater&) & = default; ratio_greater_equal& operator=(const ratio_greater_equal&) & = default; |
20.4.2.3 [tuple.helper] | template <class... Types> class tuple_size<tuple<Types...>> | tuple_size& operator=(const tuple_size&) & = default; |
20.4.2.3 [tuple.helper] | template <size_t I, class... Types> requires True<(I < sizeof...(Types))> class tuple_element<I, tuple<Types...>> | tuple_element& operator=(const tuple_element&) & = default; |
20.5.3 [meta.help] | class template integral_constant | integral_constant& operator=(const integral_constant&) & = default; |
20.5.7 [meta.trans.other]/3 | template <class T> struct common_type<T> template <class T, class U> struct common_type<T, U> template <class T, class U, class... V>> struct common_type<T, U, V...> | common_type& operator=(const common_type&) & = default; |
20.6.3 [base]/1 | class template unary_function class template binary_function |
unary_function& operator=(const unary_function&) & = default; binary_function& operator=(const binary_function&) & = default; |
20.6.4 [func.ret] | template <class Fn, class... ArgTypes> struct result_of<Fn(ArgTypes...)> | result_of& operator=(const result_of&) & = default; |
20.6.6 [identity.operation] | class template identity | identity& operator=(const identity&) & = default; |
20.6.7 [arithmetic.operations] | class template plus class template minus class template multiplies class template divides class template modulus class template negate |
plus& operator=(const plus&) & = default; minus& operator=(const minus&) & = default; multiplies& operator=(const multiplies&) & = default; divides& operator=(const divides&) & = default; modulus& operator=(const modulus&) & = default; negate& operator=(const negate&) & = default; |
20.6.8 [comparisons] | class template equal_to class template not_equal_to class template greater class template less class template greater_equal class template less_equal |
equal_to& operator=(const equal_to&) & = default; not_equal_to& operator=(const not_equal_to&) & = default; greater& operator=(const greater&) & = default; less& operator=(const less&) & = default; greater_equal& operator=(const greater_equal&) & = default; less_equal& operator=(const less_equal&) & = default; |
20.6.9 [logical.operations] | class template logical_and class template logical_or class template logical_not |
logical_and& operator=(const logical_and&) & = default; logical_or& operator=(const logical_or&) & = default; logical_not& operator=(const logical_not&) & = default; |
20.6.10 [bitwise.operations] | class template bit_and class template bit_or class template bit_xor |
bit_and& operator=(const bit_and&) & = default; bit_or& operator=(const bit_or&) & = default; bit_xor& operator=(const bit_xor&) & = default; |
20.6.11 [negators] | class template unary_negate class template binary_negate |
unary_negate& operator=(const unary_negate&) & = default; binary_negate& operator=(const binary_negate&) & = default; |
20.6.12.1.1 [func.bind.isbind] | class template is_bind_expression | is_bind_expression& operator=(const is_bind_expression&) & = default; |
20.6.12.1.2 [func.bind.isplace] | class template is_placeholder | is_placeholder& operator=(const is_placeholder&) & = default; |
20.6.13 [function.pointer.adaptors] | class template pointer_to_unary_function class template pointer_to_binary_function |
pointer_to_unary_function& operator=(const pointer_to_unary_function&) & = default; pointer_to_binary_function& operator=(const pointer_to_binary_function&) & = default; |
20.6.14 [member.pointer.adaptors] | class template mem_fun_t class template mem_fun1_t class template mem_fun_ref_t class template mem_fun1_ref_t class template const_mem_fun_t class template const_mem_fun1_t class template const_mem_fun_ref_t class template const_mem_fun1_ref_t |
mem_fun_t& operator=(const mem_fun_t&) & = default; mem_fun1_t& operator=(const mem_fun1_t&) & = default; mem_fun_ref_t& operator=(const mem_fun_ref_t&) & = default; mem_fun1_ref_t& operator=(const mem_fun1_ref_t&) & = default; const_mem_fun_t& operator=(const const_mem_fun_t&) & = default; const_mem_fun1_t& operator=(const const_mem_fun1_t&) & = default; const_mem_fun_ref_t& operator=(const const_mem_fun_ref_t&) & = default; const_mem_fun1_ref_t& operator=(const const_mem_fun1_ref_t&) & = default; |
20.6.16.1 [func.wrap.badcall]/1 | class bad_function_call | bad_function_call& operator=(const bad_function_call&) & = default; |
20.6.17 [unord.hash]/1 | class template hash | hash& operator=(const hash&) & = default; |
20.7 [memory]/2 | struct allocator_arg_t template <Allocator OuterA, Allocator InnerA> struct is_scoped_allocator<scoped_allocator_adaptor<OuterA, InnerA>> template <Allocator OuterA, Allocator InnerA> struct allocator_propagate_never<scoped_allocator_adaptor<OuterA, InnerA>> |
allocator_arg_t& operator=(const allocator_arg_t&) & = default; is_scoped_allocator& operator=(const is_scoped_allocator&) & = default; allocator_propagate_never& operator=(const allocator_propagate_never&) & = default; |
20.7.1 [allocator.tag] | struct allocator_arg_t | allocator_arg_t& operator=(const allocator_arg_t&) & = default; |
20.7.3 [allocator.element.concepts] | class template is_scoped_allocator | is_scoped_allocator& operator=(const is_scoped_allocator&) & = default; |
20.7.4 [allocator.propagation] | class template allocator_propagate_never class template allocator_propagate_on_copy_construction class template allocator_propagate_on_move_assignment class template allocator_propagate_on_copy_assignment |
allocator_propagate_never& operator=(const allocator_propagate_never&) & = default; allocator_propagate_on_copy_construction& operator=(const allocator_propagate_on_copy_construction&) & = default; allocator_propagate_on_move_assignment& operator=(const allocator_propagate_on_move_assignment&) & = default; allocator_propagate_on_copy_assignment& operator=(const allocator_propagate_on_copy_assignment&) & = default; |
20.7.5 [allocator.propagation.map] | class template allocator_propagation_map | allocator_propagation_map& operator=(const allocator_propagation_map&) & = default; |
20.7.6 [default.allocator] | template <> class allocator<void> class template allocator |
allocator& operator=(const allocator&) & = default; |
20.7.7 [allocator.adaptor]/1 | template<Allocator OuterA> class scoped_allocator_adaptor<OuterA, unspecified allocator type> | scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) & = default; |
20.7.7 [allocator.adaptor]/1 | template<typename OuterA, typename InnerA> class scoped_allocator_adaptor | scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) & = default; |
20.7.12.1.1 [unique.ptr.dltr.dflt] | class template default_delete | default_delete& operator=(const default_delete&) & = default; |
20.7.12.1.2 [unique.ptr.dltr.dflt1] | template <class T> struct default_delete<T[]> | default_delete& operator=(const default_delete&) & = default; |
20.7.13.1 [util.smartptr.weakptr] | class template bad_weak_ptr | bad_weak_ptr& operator=(const bad_weak_ptr&) & = default; |
20.7.13.4 [util.smartptr.ownerless] | template <class T> struct owner_less<shared_ptr<T>> template <class T> struct owner_less<weak_ptr<T>> |
owner_less& operator=(const owner_less&) & = default; |
20.8.2.1 [time.traits.is_fp] | class template treat_as_floating_point | treat_as_floating_point& operator=(const treat_as_floating_point&) & = default; |
20.8.2.2 [time.traits.duration_values] | class template duration_values | duration_values& operator=(const duration_values&) & = default; |
20.8.2.3 [time.traits.specializations] | template <class Rep1, class Period1, class Rep2, class Period2> struct common_type<<chrono::duration<Rep1, Period1>, chrono::duration<Rep2, Period2>> template <class Clock, class Duration1, class Duration2> struct common_type<<chrono:::time_point<Clock, Duration1>, chrono:::time_point<Clock, Duration2>> |
common_type& operator=(const common_type&) & = default; |
20.8.4 [time.point] | class template time_point | time_point& operator=(const time_point&) & = default; |
20.8.5.1 [time.clock.system]/1 | class system_clock | system_clock& operator=(const system_clock&) & = default; |
20.8.5.2 [time.clock.monotonic]/2 | class monotonic_clock | monotonic_clock& operator=(const monotonic_clock&) & = default; |
20.8.5.3 [time.clock.hires]/1 | class high_resolution_clock | high_resolution_clock& operator=(const high_resolution_clock&) & = default; |
21.1.3.1 [char.traits.specializations.char] | template<> class char_traits<char> | char_traits& operator=(const char_traits&) & = default; |
21.1.3.2 [char.traits.specializations.char16_t] | template<> class char_traits<char16_t> | char_traits& operator=(const char_traits&) & = default; |
21.1.3.3 [char.traits.specializations.char32_t] | template<> class char_traits<char32_t> | char_traits& operator=(const char_traits&) & = default; |
21.1.3.4 [char.traits.specializations.wchar.t] | template<> class char_traits<wchar_t> | char_traits& operator=(const char_traits&) & = default; |
22.1.3.2.2 [conversions.string]/2 | class template wstring_convert | wstring_convert& operator=(const wstring_convert&) & = default; |
22.2.1 [category.ctype] | class ctype_base | ctype_base& operator=(const ctype_base&) & = default; |
22.2.1.4 [locale.codecvt] | class codecvt_base | codecvt_base& operator=(const codecvt_base&) & = default; |
22.2.5.1 [locale.time.get] | class time_base | time_base& operator=(const time_base&) & = default; |
22.2.6.3 [locale.moneypunct] | class money_base | money_base& operator=(const money_base&) & = default; |
22.2.7.1 [locale.messages] | class messages_base | messages_base& operator=(const messages_base&) & = default; |
23.2.1 [array]/3 | class template array | array& operator=(const array&) & = default; |
23.2.5.1.1 [queue.defn] | class template queue | queue& operator=(const queue&) & = default; |
23.2.5.2 [priority.queue] | class template priority_queue | priority_queue& operator=(const priority_queue&) & = default; |
23.2.5.3.1 [stack.defn] | class template stack | stack& operator=(const stack&) & = default; |
23.3.1 [map]/2 | class template map::value_compare | value_compare& operator=(const value_compare&) & = default; |
23.3.2 [multimap]/2 | class template multimap::value_compare | value_compare& operator=(const value_compare&) & = default; |
24.2 [iterator.synopsis] | struct input_iterator_tag struct output_iterator_tag struct forward_iterator_tag struct bidirectional_iterator_tag struct random_access_iterator_tag |
input_iterator_tag& operator=(const input_iterator_tag&) & = default; output_iterator_tag& operator=(const output_iterator_tag&) & = default; forward_iterator_tag& operator=(const forward_iterator_tag&) & = default; bidirectional_iterator_tag& operator=(const bidirectional_iterator_tag&) & = default; random_access_iterator_tag& operator=(const random_access_iterator_tag&) & = default; |
24.4.2.1 [back.insert.iterator] | class template back_insert_iterator | back_insert_iterator& operator=(const back_insert_iterator&) & = default; |
24.4.2.3 [front.insert.iterator] | class template front_insert_iterator | front_insert_iterator& operator=(const front_insert_iterator&) & = default; |
24.4.2.5 [insert.iterator] | class template insert_iterator | insert_iterator& operator=(const insert_iterator&) & = default; |
24.5.1 [istream.iterator]/3 | class template istream_iterator | istream_iterator& operator=(const istream_iterator&) & = default; |
24.5.2 [ostream.iterator]/2 | class template ostream_iterator | ostream_iterator& operator=(const ostream_iterator&) & = default; |
24.5.3 [istreambuf.iterator] | class template istreambuf_iterator | istreambuf_iterator& operator=(const istreambuf_iterator&) & = default; |
24.5.3.1 [istreambuf.iterator::proxy] | class template istreambuf_iterator::proxy | proxy& operator=(const proxy&) & = default; |
24.5.4 [ostreambuf.iterator] | class template ostreambuf_iterator | ostreambuf_iterator& operator=(const ostreambuf_iterator&) & = default; |
26.4.3.1 [rand.eng.lcong] | class template linear_congruential_engine | linear_congruential_engine& operator=(const linear_congruential_engine&) & = default; |
26.4.3.2 [rand.eng.mers]/3 | class template mersenne_twister_engine | mersenne_twister_engine& operator=(const mersenne_twister_engine&) & = default; |
26.4.3.3 [rand.eng.sub]/4 | class template subtract_with_carry_engine | subtract_with_carry_engine& operator=(const subtract_with_carry_engine&) & = default; |
26.4.4.1 [rand.adapt.disc]/3 | class template discard_block_engine | discard_block_engine& operator=(const discard_block_engine&) & = default; |
26.4.4.2 [rand.adapt.ibits]/4 | class template independent_bits_engine | independent_bits_engine& operator=(const independent_bits_engine&) & = default; |
26.4.4.3 [rand.adapt.shuf]/3 | class template shuffle_order_engine | shuffle_order_engine& operator=(const shuffle_order_engine&) & = default; |
26.4.7.1 [rand.util.seedseq]/2 | class seed_seq | seed_seq& operator=(const seed_seq&) & = default; |
26.4.8.1.1 [rand.dist.uni.int]/1 | class template uniform_int_distribution | uniform_int_distribution& operator=(const uniform_int_distribution&) & = default; |
26.4.8.1.2 [rand.dist.uni.real]/1 | class template uniform_real_distribution | uniform_real_distribution& operator=(const uniform_real_distribution&) & = default; |
26.4.8.2.1 [rand.dist.bern.bernoulli]/1 | class bernoulli_distribution | bernoulli_distribution& operator=(const bernoulli_distribution&) & = default; |
26.4.8.2.2 [rand.dist.bern.bin]/1 | class template binomial_distribution | binomial_distribution& operator=(const binomial_distribution&) & = default; |
26.4.8.2.3 [rand.dist.bern.geo]/1 | class template geometric_distribution | geometric_distribution& operator=(const geometric_distribution&) & = default; |
26.4.8.2.4 [rand.dist.bern.negbin]/1 | class template negative_binomial_distribution | negative_binomial_distribution& operator=(const negative_binomial_distribution&) & = default; |
26.4.8.3.1 [rand.dist.pois.poisson]/1 | class template poisson_distribution | poisson_distribution& operator=(const poisson_distribution&) & = default; |
26.4.8.3.2 [rand.dist.pois.exp]/1 | class template exponential_distribution | exponential_distribution& operator=(const exponential_distribution&) & = default; |
26.4.8.3.3 [rand.dist.pois.gamma]/1 | class template gamma_distribution | gamma_distribution& operator=(const gamma_distribution&) & = default; |
26.4.8.3.4 [rand.dist.pois.weibull]/1 | class template weibull_distribution | weibull_distribution& operator=(const weibull_distribution&) & = default; |
26.4.8.3.5 [rand.dist.pois.extreme]/1 | class template extreme_value_distribution | extreme_value_distribution& operator=(const extreme_value_distribution&) & = default; |
26.4.8.4.1 [rand.dist.norm.normal]/1 | class template normal_distribution | normal_distribution& operator=(const normal_distribution&) & = default; |
26.4.8.4.2 [rand.dist.norm.lognormal]/1 | class template lognormal_distribution | lognormal_distribution& operator=(const lognormal_distribution&) & = default; |
26.4.8.4.3 [rand.dist.norm.chisq]/1 | class template chi_squared_distribution | chi_squared_distribution& operator=(const chi_squared_distribution&) & = default; |
26.4.8.4.4 [rand.dist.norm.cauchy]/1 | class template cauchy_distribution | cauchy_distribution& operator=(const cauchy_distribution&) & = default; |
26.4.8.4.5 [rand.dist.norm.f]/1 | class template fisher_f_distribution | fisher_f_distribution& operator=(const fisher_f_distribution&) & = default; |
26.4.8.4.6 [rand.dist.norm.t]/1 | class template student_t_distribution | student_t_distribution& operator=(const student_t_distribution&) & = default; |
26.4.8.5.1 [rand.dist.samp.discrete]/1 | class template discrete_distribution | discrete_distribution& operator=(const discrete_distribution&) & = default; |
26.4.8.5.2 [rand.dist.samp.pconst]/1 | class template piecewise_constant_distribution | piecewise_constant_distribution& operator=(const piecewise_constant_distribution&) & = default; |
26.4.8.5.3 [rand.dist.samp.genpdf]/1 | class template general_pdf_distribution | general_pdf_distribution& operator=(const general_pdf_distribution&) & = default; |
26.5.4 [class.slice] | class slice | slice& operator=(const slice&) & = default; |
26.5.6 [class.gslice] | class gslice | gslice& operator=(const gslice&) & = default; |
27.4.2.1.1 [ios::failure] | class ios_base::failure | failure& operator=(const failure&) & = default; |
27.4.2.1.6 [ios::Init] | class ios_base::Init | Init& operator=(const Init&) & = default; |
27.4.3 [fpos] | class template fpos | fpos& operator=(const fpos&) & = default; |
28.6 [re.badexp] | class regex_error | regex_error& operator=(const regex_error&) & = default; |
28.7 [re.traits] | class template regex_traits | regex_traits& operator=(const regex_traits&) & = default; |
28.9 [re.submatch] | class template sub_match | sub_match& operator=(const sub_match&) & = default; |
30.2.1.1 [thread.thread.id] | class thread::id | id& operator=(const id&) & = default; |
30.3.3 [thread.lock]/2 | struct defer_lock_t struct try_to_lock_t struct adopt_lock_t |
defer_lock_t& operator=(const defer_lock_t&) & = default; try_to_lock_t& operator=(const try_to_lock_t&) & = default; adopt_lock_t& operator=(const adopt_lock_t&) & = default; |
30.5.3 [futures.future_error] | class future_error | future_error& operator=(const future_error&) & = default; |
30.5.7 [futures.allocators] | template <class R, class Alloc> struct uses_allocator<promise<R>, Alloc> template <class R> struct constructible_with_allocator_prefix<promise<R>> |
uses_allocator& operator=(const uses_allocator&) & = default; constructible_with_allocator_prefix& operator=(const constructible_with_allocator_prefix&) & = default; |
Change 23.2.1.1 [array.cons], as a consequence of the proposed change of [array] by Table 2:
Class array relies on the implicitly-declared special member functions (12.1, 12.4, and 12.8), and its explicitly-defaulted assignment operator (8.4, [dcl.fct.def]), to conform to the container requirements table in 23.1.
Table 3 lists the assignment operators that are excluded from this proposal. The following types are excluded:
Table 3. Assignment operators that are not affected by the proposal
Section | Line |
20.2.6 [template.bitset] | reference& operator=(bool x); // for b[i] = x; |
20.2.6 [template.bitset] | reference& operator=(const reference&); // for b[i] = b[j]; |
20.4.2 [tuple.tuple] | requires CopyAssignable<Types>... tuple& operator=(const tuple&); |
20.4.2 [tuple.tuple] | tuple& operator=(const tuple<UTypes...>&); |
20.4.2 [tuple.tuple] | tuple& operator=(tuple<UTypes...>&&); |
20.4.2.1 [tuple.cnstr] | requires CopyAssignable<Types>... tuple& operator=(const tuple& u); |
20.4.2.1 [tuple.cnstr] | requires MoveAssignable<Types>... tuple& operator=(tuple&& u); |
20.4.2.1 [tuple.cnstr] | tuple& operator=(const tuple<UTypes...>& u); |
20.4.2.1 [tuple.cnstr] | tuple& operator=(tuple<UTypes...>&& u); |
20.4.2.1 [tuple.cnstr]/10 | tuple& operator=(const pair<UTypes...>&); |
20.4.2.1 [tuple.cnstr] | tuple& operator=(pair<UTypes...>&&); |
23.2.7 [vector.bool] | reference& operator=(const bool x); |
23.2.7 [vector.bool] | reference& operator=(const reference& x); |
26.5.5 [template.slice.array] | const slice_array& operator=(const slice_array&) const; |
26.5.5.1 [slice.arr.assign] | const slice_array& operator=(const slice_array&) const; |
26.5.7 [template.gslice.array] | const gslice_array& operator=(const gslice_array&) const; |
26.5.7.1 [gslice.array.assign] | const gslice_array& operator=(const gslice_array&) const; |
26.5.8 [template.mask.array] | const mask_array& operator=(const mask_array&) const; |
26.5.8.1 [mask.array.assign] | const mask_array& operator=(const mask_array&) const; |
26.5.9 [template.indirect.array] | const indirect_array& operator=(const indirect_array&) const; |
26.5.9.1 [indirect.array.assign] | const indirect_array& operator=(const indirect_array&) const; |
D.9.1 [auto.ptr] | auto_ptr& operator=(auto_ptr&) throw(); |
D.9.1 [auto.ptr] | template<class Y> auto_ptr& operator=(auto_ptr<Y>&) throw(); |
D.9.1 [auto.ptr] | auto_ptr& operator=(auto_ptr_ref<X> r) throw(); |
D.9.1.1 [auto.ptr.cons] | auto_ptr& operator=(auto_ptr& a) throw(); |
D.9.1.1 [auto.ptr.cons] | template<class Y> auto_ptr& operator=(auto_ptr<Y>& a) throw(); |
D.9.1.3 [auto.ptr.conv] | auto_ptr& operator=(auto_ptr_ref<X> r) throw() |
18.6.1 [type.info] | type_info& operator=(const type_info& rhs) = delete; // cannot be copied |
19.4.1.1 [syserr.errcat.overview] | error_category& operator=(const error_category&) = delete; |
20.7.12.2 [unique.ptr.single] | unique_ptr& operator=(const unique_ptr&) = delete; |
20.7.12.2 [unique.ptr.single] | template <class U, class E> unique_ptr& operator=(const unique_ptr<U, E>&) = delete; |
20.7.12.3 [unique.ptr.runtime] | unique_ptr& operator=(const unique_ptr&) = delete; |
20.7.13.2 [util.smartptr.shared] | template <class Y, class D> shared_ptr& operator=(const unique_ptr<Y, D>& r) = delete; |
22.1.1.1.2 [locale.facet] | void operator=(const facet&) = delete; |
22.1.1.1.3 [locale.id] | void operator=(const id&) = delete; |
26.4.6 [rand.device] | void operator=(const random_device& ) = delete; |
27.4.2 [ios.base] | ios_base& operator=(const ios_base&) = delete; |
27.4.4 [ios] | basic_ios& operator=(const basic_ios&) = delete; |
27.6.1.1.3 [istream::sentry] | sentry& operator=(const sentry&) = delete; |
27.6.2.4 [ostream::sentry] | sentry& operator=(const sentry&) = delete; |
29.3.1 [atomics.types.integral] | atomic_bool& operator=(const atomic_bool&) = delete; |
29.3.1 [atomics.types.integral] | atomic_itype& operator=(const atomic_itype &) = delete; |
29.3.2 [atomics.types.address] | atomic_address& operator=(const atomic_address&) = delete; |
29.3.3 [atomics.types.generic] | atomic& operator=(const atomic&) = delete; |
29.3.3 [atomics.types.generic] | atomic& operator=(const atomic&) = delete; |
29.3.3 [atomics.types.generic] | atomic& operator=(const atomic&) = delete; |
29.5 [atomics.flag] | atomic_flag& operator=(const atomic_flag&) = delete; |
30.2.1 [thread.thread.class] | thread& operator=(const thread&) = delete; |
30.3 [thread.mutex] | once_flag& operator=(const once_flag&) = delete; |
30.3.1.1 [thread.mutex.class] | mutex& operator=(const mutex&) = delete; |
30.3.1.2 [thread.mutex.recursive] | recursive_mutex& operator=(const recursive_mutex&) = delete; |
30.3.2.1 [thread.timedmutex.class] | timed_mutex& operator=(const timed_mutex&) = delete; |
30.3.2.2 [thread.timedmutex.recursive] | recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; |
30.3.3.1 [thread.lock.guard] | lock_guard& operator=(lock_guard const&) = delete; |
30.3.3.2 [thread.lock.unique] | unique_lock& operator=(unique_lock const&) = delete; |
30.4.1 [thread.condition.condvar] | condition_variable& operator=(const condition_variable&) = delete; |
30.4.2 [thread.condition.condvarany] | condition_variable_any& operator=(const condition_variable_any&) = delete; |
30.5.4 [futures.unique_future] | unique_future& operator=(const unique_future& rhs) = delete; |
30.5.5 [future.shared_future] | shared_future & operator=(const shared_future& rhs) = delete; |
30.5.6 [futures.promise] | promise & operator=(const promise& rhs) = delete; |
30.5.8 [futures.task] | packaged_task& operator=(packaged_task&) = delete; |
Special thanks to Alberto Ganesh Barbati, Walter E. Brown, Sebastian Gesemann, Howard Hinnant, and Bronek Kozicki for their help and feedback. Thanks very much as well to the Dutch HCC C gebruikersgroep.
Daniel Krügler works as a software developer at Bruker Daltonik, Bremen, Germany. Niels Dekker works as a scientific programmer at the Division of Image Processing (LKEB), Leiden University Medical Center, The Netherlands.