This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of CD1 status.

### 253. valarray helper functions are almost entirely useless

Section: 28.6.2.2 [valarray.cons], 28.6.2.3 [valarray.assign] Status: CD1 Submitter: Robert Klarer Opened: 2000-07-31 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [valarray.cons].

View all issues with CD1 status.

Discussion:

This discussion is adapted from message c++std-lib-7056 posted November 11, 1999. I don't think that anyone can reasonably claim that the problem described below is NAD.

These valarray constructors can never be called:

       template <class T>
             valarray<T>::valarray(const slice_array<T> &);
       template <class T>
             valarray<T>::valarray(const gslice_array<T> &);
       template <class T>
             valarray<T>::valarray(const mask_array<T> &);
       template <class T>
             valarray<T>::valarray(const indirect_array<T> &);

Similarly, these valarray assignment operators cannot be called:

         template <class T>
         valarray<T> valarray<T>::operator=(const slice_array<T> &);
         template <class T>
         valarray<T> valarray<T>::operator=(const gslice_array<T> &);
         template <class T>
         valarray<T> valarray<T>::operator=(const mask_array<T> &);
         template <class T>
         valarray<T> valarray<T>::operator=(const indirect_array<T> &);

Please consider the following example:

       #include <valarray>
       using namespace std;

       int main()
       {
           valarray<double> va1(12);
           valarray<double> va2(va1[slice(1,4,3)]); // line 1
       }

Since the valarray va1 is non-const, the result of the sub-expression va1[slice(1,4,3)] at line 1 is an rvalue of type const std::slice_array<double>. This slice_array rvalue is then used to construct va2. The constructor that is used to construct va2 is declared like this:

         template <class T>
         valarray<T>::valarray(const slice_array<T> &);

Notice the constructor's const reference parameter. When the constructor is called, a slice_array must be bound to this reference. The rules for binding an rvalue to a const reference are in 8.5.3, paragraph 5 (see also 13.3.3.1.4). Specifically, paragraph 5 indicates that a second slice_array rvalue is constructed (in this case copy-constructed) from the first one; it is this second rvalue that is bound to the reference parameter. Paragraph 5 also requires that the constructor that is used for this purpose be callable, regardless of whether the second rvalue is elided. The copy-constructor in this case is not callable, however, because it is private. Therefore, the compiler should report an error.

Since slice_arrays are always rvalues, the valarray constructor that has a parameter of type const slice_array<T> & can never be called. The same reasoning applies to the three other constructors and the four assignment operators that are listed at the beginning of this post. Furthermore, since these functions cannot be called, the valarray helper classes are almost entirely useless.

Proposed resolution:

slice_array:

- Make the copy constructor and copy-assignment operator declarations public in the slice_array class template definition in 28.6.5 [template.slice.array]
- remove paragraph 3 of 28.6.5 [template.slice.array]
- remove the copy constructor declaration from [cons.slice.arr]
- change paragraph 1 of [cons.slice.arr] to read "This constructor is declared to be private. This constructor need not be defined."
- remove the first sentence of paragraph 1 of 28.6.5.2 [slice.arr.assign]
- Change the first three words of the second sentence of paragraph 1 of 28.6.5.2 [slice.arr.assign] to "These assignment operators have"

gslice_array:

- Make the copy constructor and copy-assignment operator declarations public in the gslice_array class template definition in 28.6.7 [template.gslice.array]
- remove the note in paragraph 3 of 28.6.7 [template.gslice.array]
- remove the copy constructor declaration from [gslice.array.cons]
- change paragraph 1 of [gslice.array.cons] to read "This constructor is declared to be private. This constructor need not be defined."
- remove the first sentence of paragraph 1 of 28.6.7.2 [gslice.array.assign]
- Change the first three words of the second sentence of paragraph 1 of 28.6.7.2 [gslice.array.assign] to "These assignment operators have"

mask_array:

- Make the copy constructor and copy-assignment operator declarations public in the mask_array class template definition in 28.6.8 [template.mask.array]
- remove the note in paragraph 2 of 28.6.8 [template.mask.array]
- remove the copy constructor declaration from [mask.array.cons]
- change paragraph 1 of [mask.array.cons] to read "This constructor is declared to be private. This constructor need not be defined."
- remove the first sentence of paragraph 1 of 28.6.8.2 [mask.array.assign]
- Change the first three words of the second sentence of paragraph 1 of 28.6.8.2 [mask.array.assign] to "These assignment operators have"

indirect_array:

- Make the copy constructor and copy-assignment operator declarations public in the indirect_array class definition in 28.6.9 [template.indirect.array]
- remove the note in paragraph 2 of 28.6.9 [template.indirect.array]
- remove the copy constructor declaration from [indirect.array.cons]
- change the descriptive text in [indirect.array.cons] to read "This constructor is declared to be private. This constructor need not be defined."
- remove the first sentence of paragraph 1 of 28.6.9.2 [indirect.array.assign]
- Change the first three words of the second sentence of paragraph 1 of 28.6.9.2 [indirect.array.assign] to "These assignment operators have"

[Proposed resolution was modified in Santa Cruz: explicitly make copy constructor and copy assignment operators public, instead of removing them.]

Rationale:

Keeping the valarray constructors private is untenable. Merely making valarray a friend of the helper classes isn't good enough, because access to the copy constructor is checked in the user's environment.

Making the assignment operator public is not strictly necessary to solve this problem. A majority of the LWG (straw poll: 13-4) believed we should make the assignment operators public, in addition to the copy constructors, for reasons of symmetry and user expectation.