Section: 220.127.116.11 [valarray.cons] Status: C++11 Submitter: Martin Sebor Opened: 2007-01-28 Last modified: 2016-02-10
Priority: Not Prioritized
View all other issues in [valarray.cons].
View all issues with C++11 status.
Section 29.3 [numeric.requirements], p1 suggests that a
valarray specialization on a type
satisfies the requirements enumerated in the paragraph is itself a
valid type on which
valarray may be instantiated
(Footnote 269 makes this clear). I.e.,
valarray<valarray<T> > is valid as long as
T is valid. However, since implementations of
valarray are permitted to initialize storage allocated by
the class by invoking the default ctor of
T followed by
the copy assignment operator, such implementations of
valarray wouldn't work with (perhaps user-defined)
valarray whose assignment operator had
undefined behavior when the size of its argument didn't match the size
*this. By "wouldn't work" I mean that it would
be impossible to resize such an array of arrays by calling the
resize() member function on it if the function used the
copy assignment operator after constructing all elements using the
default ctor (e.g., by invoking
new value_type[N]) to
obtain default-initialized storage) as it's permitted to do.
Stated more generally, the problem is that
valarray<valarray<T> >::resize(size_t) isn't
required or guaranteed to have well-defined semantics for every type
T that satisfies all requirements in
I believe this problem was introduced by the adoption of the
resolution outlined in N0857,
Assignment of valarrays, from 1996. The copy assignment
operator of the original numerical array classes proposed in N0280,
as well as the one proposed in N0308
(both from 1993), had well-defined semantics for arrays of unequal
size (the latter explicitly only when
*this was empty;
assignment of non empty arrays of unequal size was a runtime error).
The justification for the change given in N0857 was the "loss of performance [deemed] only significant for very simple operations on small arrays or for architectures with very few registers."
Since tiny arrays on a limited subset of hardware architectures are
likely to be an exceedingly rare case (despite the continued
popularity of x86) I propose to revert the resolution and make the
behavior of all
valarray assignment operators
well-defined even for non-conformal arrays (i.e., arrays of unequal
size). I have implemented this change and measured no significant
degradation in performance in the common case (non-empty arrays of
equal size). I have measured a 50% (and in some cases even greater)
speedup in the case of assignments to empty arrays versus calling
resize() first followed by an invocation of the copy
[ Bellevue: ]
If no proposed wording by June meeting, this issue should be closed NAD.
[ 2009-07 Frankfurt ]
Move resolution 1 to Ready.
Howard: second resolution has been commented out (made invisible). Can be brought back on demand.
Change 18.104.22.168 [valarray.assign], p1 as follows:
valarray<T>& operator=(const valarray<T>&);
-1- Each element of the
*thisarray is assigned the value of the corresponding element of the argument array.
The resulting behavior is undefined ifthe length of the argument array is not equal to the length of the *this array .
And add a new paragraph just below paragraph 1 with the following text:
Also add the following paragraph to 22.214.171.124 [valarray.assign], immediately after p4:
[ pre-Sophia Antipolis, Martin adds the following compromise wording, but prefers the original proposed resolution: ]
[ Kona (2007): Gaby to propose wording for an alternative resolution in which you can assign to a valarray of size 0, but not to any other valarray whose size is unequal to the right hand side of the assignment. ]