|
Boost-Commit : |
From: dgregor_at_[hidden]
Date: 2008-05-29 15:58:53
Author: dgregor
Date: 2008-05-29 15:58:52 EDT (Thu, 29 May 2008)
New Revision: 45919
URL: http://svn.boost.org/trac/boost/changeset/45919
Log:
Add issue for CopyAssignable/HasCopyAssign in container assignment
Added:
sandbox/committee/concepts/issues/issues/issue34.xml (contents, props changed)
Added: sandbox/committee/concepts/issues/issues/issue34.xml
==============================================================================
--- (empty file)
+++ sandbox/committee/concepts/issues/issues/issue34.xml 2008-05-29 15:58:52 EDT (Thu, 29 May 2008)
@@ -0,0 +1,186 @@
+<?xml version='1.0' encoding='iso-8859-1' standalone='no'?>
+<!DOCTYPE issue SYSTEM "lwg-issue.dtd" [
+ <!ENTITY nbsp " ">
+] >
+
+<issue num="34" status="Open">
+<title>Copy/move requirements on container members</title>
+<section><sref ref="[containers]"/></section>
+<submitter>Howard Hinnant</submitter>
+<date>22 May 2008</date>
+
+<discussion>
+ <p>In N2623 I note that the requirements on each container
+ assignment look like:</p>
+
+<pre>
+requires ConstructibleAsElement<Alloc, T, const T&>
+ vector<T,Allocator>& operator=(const vector<T,Allocator>& x);
+</pre>
+
+<p>Why is <code>T</code> not required to
+be <code>CopyAssignable</code>? We have a history of wanting to reuse
+capacity/nodes whatever, whenever we can. This is a tremendous
+performance advantage over
+a <code>clear()</code>/<code>push_back()</code> algorithm.</p>
+
+<p>I'm aware that a container could always overload each assignment
+member for types that are <code>CopyAssignable</code>, and make the
+optimization. I'm greatly concerned about doubling the size of the
+entire std::library by doing such overloading in so many places where
+this philosophy is currently proposed. Concepts are already going to
+extract a very significant compile-time penalty (no one knows how much
+at this point, conceptgcc is a worst (and unacceptable) case). I
+don't want to further aggravate that very real problem.</p>
+
+<p>These requirements have an interesting history. In the following,
+CA=<code>CopyAssignable</code>, CC=<code>CopyConstructible</code>,
+MA=<code>MoveAssignable</code>, and MC=<code>MoveAssignable</code>.
+The library "move papers" were written in 2005. At that time we had a
+blanket CA/CC requirement on the containers. Howard wrote the move
+papers against that, mechanically substituting in MA/MC for CA/CC.</p>
+
+<p>After the move papers were written, and before they were accepted,
+LWG 276 was settled, removing the CA requirement for all the
+node-based containers except <code>list::assign</code>. It was still
+required for all of vector and deque (if I recall correctly). Then
+the move papers were accepted, subsequently accidently reversing LWG
+276.</p>
+
+<p>The addition of scoped allocators (N2554) removed the blanket MA/MC
+ requirement, added by the move papers,
+ using <code>ConstructibleAsElement</code> without CA/CC/MA/MC. LWG 704
+ (submitted prior to pre-scoped allocators and emplace) attempts to
+ straighten out the message. This issue includes the minimum
+ requirements for each container member at the time the issue was
+ written (May 20, 2007). The table doesn't specifically mention
+ C::operator=(const C&) because those requirements should be
+ identical to c1.assign(c2.begin(), c2.end()) which is listed.</p>
+</discussion>
+
+<resolution>
+ <p>(Proposed resolution by Doug Gregor)</p>
+ <p>In [deque], change the definition of class template <code>deque</code> as follows:</p>
+ <pre>
+template <ObjectType T, RandomAccessAllocator Alloc = allocator<T> >
+requires Destructible<T>
+class deque {
+public:
+ // ...
+
+ requires ConstructibleAsElement<Alloc, T, const T&> <ins>&& CopyAssignable<T></ins>
+ deque<T,Allocator>& operator=(const deque<T,Allocator>& x);
+ deque<T,Allocator>& operator=(const deque<T,Allocator>&& x);
+ template <InputIterator Iter>
+ requires ConstructibleAsElement<Alloc, T, Iter::reference> <ins>&& HasCopyAssign<T, Iter::reference></ins>
+ void assign(Iter first, Iter last);
+ requires ConstructibleAsElement<Alloc, T, const T&> <ins>&& CopyAssignable<T></ins>
+ void assign(size_type n, const T& t);
+
+ // ...
+ requires DefaultConstructible<T> <del>&& MoveAssignable<T></del>
+ void resize(size_type sz);
+ requires ConstructibleAsElement<Alloc, T, const T&> <del>&& MoveAssignable<T></del>
+ void resize(size_type sz, const T& c);
+};
+ </pre>
+ <p><i>Note</i>: LWG 704 says that <code>resize</code> for a <cod>deque</cod>
+ requires <code>MoveConstructible</code>, but it does not (because
+ one never needs to move from an existing block).</p>
+
+ <p>In [forwardlist], change the definition of class template <code>forward_list</code> as follows:</p>
+ <pre>
+template <ObjectType T, Allocator Alloc = allocator<T> >
+requires Destructible<T>
+class forward_list {
+public:
+ // ...
+ requires ConstructibleAsElement<Alloc, T, const T&> <ins>&& CopyAssignable<T></ins>
+ forward_list<T,Alloc>& operator=(const forward_list<T,Alloc>& x);
+ forward_list<T,Alloc>& operator=(forward_list<T,Alloc>&& x);
+ template <class InputIteratorInputIterator Iter>
+ requires ConstructibleAsElement<Alloc, T, Iter::reference> <ins>&& HasCopyAssign<T, Iter::reference></ins>
+ void assign(Iter first, Iter last);
+ ConstructibleAsElement<Alloc, T, const T&> <ins>&& CopyAssignable<T></ins>
+ void assign(size_type n, const T& t);
+};
+ </pre>
+
+ <p>In [list], change the definition of class template <code>list</code> as follows:</p>
+
+ <pre>
+template <ObjectType T, Allocator Alloc = allocator<T> >
+requires Destructible<T>
+class list {
+public:
+ // ...
+ requires ConstructibleAsElement<Alloc, T, const T&> <ins>&& CopyAssignable<T></ins>
+ list<T,Alloc>& operator=(const list<T,Alloc>& x );
+ list<T,Alloc>& operator=(list<T,Alloc>&& x);
+ template <InputIterator Iter>
+ requires ConstructibleAsElement<Alloc, T, Iter::reference> <ins>&& HasCopyAssign<T, Iter::reference></ins>
+ void assign(Iter first, Iter last);
+ requires ConstructibleAsElement<Alloc, T, const T&> <ins>&& CopyAssignable<T></ins>
+ void assign(size_type n, const T& t);
+};
+ </pre>
+
+ <p>In [vector], change the definition of class template <code>vector</code>
+ as follows:</p>
+
+ <pre>
+template <ObjectType T, RandomAccessAllocator Alloc = allocator<T> >
+requires Destructible<T>
+class vector {
+public:
+ // ...
+ template <InputIterator Iter>
+ requires ConstructibleAsElement<Alloc, T, Iter::reference> && <del>ConstructibleAsElement<Alloc, T, T&&></del><ins>MoveConstructible<T></ins>
+ vector(Iter first, Iter last,
+ const Alloc& = Alloc());
+
+ // ...
+ requires ConstructibleAsElement<Alloc, T, const T&> <ins>&& CopyAssignable<T></ins>
+ vector<T,Alloc>& operator=(const vector<T,Alloc>& x);
+ vector<T,Alloc>& operator=(vector<T,Alloc>&& x);
+ template <InputIterator Iter>
+ requires ConstructibleAsElement<Alloc, T, Iter::reference>
+ <ins>&& HasCopyAssign<T, Iter::reference> && MoveConstructible<T></ins>
+ void assign(Iter first, Iter last);
+ requires ConstructibleAsElement<Alloc, T, const T&> <ins>&& CopyAssignable<T></ins>
+ void assign(size_type n, const T& u);
+
+ // ...
+ requires DefaultConstructible<T> && <del>ConstructibleAsElement<Alloc, T, T&&></del><ins>MoveConstructible<T></ins>
+ void resize(size_type sz);
+ requires ConstructibleAsElement<Alloc, T, const T&> <ins>&& MoveConstructible<T></ins>
+ void resize(size_type sz, const T& c);
+
+ // ...
+ requires <del>ConstructibleAsElement<Alloc, T, T&&> </del><ins>MoveConstructible<T></ins>
+ void reserve(size_type n);
+
+ // ...
+ template <class... Args>
+ requires ConstructibleAsElement<Alloc, T, Args&&...> && <del>ConstructibleAsElement<Alloc, T, T&&></del><ins>MoveConstructible<T></ins>
+ void push_back(Args&&... args);
+ void pop_back();
+ template <class... Args>
+ requires ConstructibleAsElement<Alloc, T, Args&&...> && <del>ConstructibleAsElement<Alloc, T, T&&></del><ins>MoveConstructible<T> && MoveAssignable<T></ins>
+ iterator emplace(const_iterator position, Args&&... args);
+ requires ConstructibleAsElement<Alloc, T, const T&> && MoveAssignable<T> <ins>&& MoveConstructible<T></ins>
+ iterator insert(const_iterator position, const T& x);
+ requires ConstructibleAsElement<Alloc, T, T&&> && MoveAssignable<T> <ins>&& MoveConstructible<T></ins>
+ void insert(const_iterator position, T&& x);
+ requires ConstructibleAsElement<Alloc, T, const T&> && MoveAssignable<T> <ins>&& MoveConstructible<T></ins>
+ void insert(const_iterator position, size_type n, const T& x);
+ template <InputIterator Iter>
+ requires ConstructibleAsElement<Alloc, T, Iter::reference>
+ <ins>&& HasCopyAssign<T, Iter::reference></ins>
+ && <del>ConstructibleAsElement<Alloc, T, T&&></del><ins>MoveConstructible<T></ins> && MoveAssignable<T>
+ void insert(const_iterator position,
+ Iter first, Iter last);
+};
+ </pre>
+</resolution>
+</issue>
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk