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

### 3074. Non-member functions for `valarray` should only deduce from the `valarray`

Section: 28.6.3 [valarray.nonmembers] Status: C++20 Submitter: Jonathan Wakely Opened: 2018-02-28 Last modified: 2021-02-25

Priority: 0

View all issues with C++20 status.

Discussion:

The expression `(std::valarray<double>{} * 2)` is ill-formed, because argument deduction fails for:

>     template<class T>
>       valarray<T> operator*(const valarray<T>&, const T&);

Is there any reason to try and deduce the argument from the scalar, instead of only deducing from the valarray and allowing implicit conversions to the scalar? i.e.

>     template<class T>
>       valarray<T> operator*(const valarray<T>&, const typename valarray<T>::value_type&);

[ 2018-03-07 Moved to Tentatively Ready after 5 positive votes on c++std-lib. ]

[2018-06 Rapperswil: Adopted]

Proposed resolution:

This wording is relative to N4727.

1. Edit 28.6.1 [valarray.syn], header `<valarray>` synopsis, as indicated:

   >     […]
   >     template<class T> valarray<T> operator* (const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<T> operator* (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator* (const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<T> operator/ (const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<T> operator/ (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator/ (const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<T> operator% (const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<T> operator% (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator% (const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<T> operator+ (const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<T> operator+ (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator+ (const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<T> operator- (const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<T> operator- (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator- (const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<T> operator^ (const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<T> operator^ (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator^ (const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<T> operator& (const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<T> operator& (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator& (const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<T> operator| (const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<T> operator| (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator| (const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<T> operator<<(const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<T> operator<<(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator<<(const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<T> operator>>(const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<T> operator>>(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator>>(const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<bool> operator&&(const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<bool> operator&&(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator&&(const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<bool> operator||(const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<bool> operator||(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator||(const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<bool> operator==(const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<bool> operator==(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator==(const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<bool> operator!=(const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<bool> operator!=(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator!=(const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<bool> operator< (const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<bool> operator< (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator< (const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<bool> operator> (const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<bool> operator> (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator> (const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<bool> operator<=(const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<bool> operator<=(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator<=(const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<bool> operator>=(const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<bool> operator>=(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator>=(const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<T> abs (const valarray<T>&);
   >     template<class T> valarray<T> acos (const valarray<T>&);
   >     template<class T> valarray<T> asin (const valarray<T>&);
   >     template<class T> valarray<T> atan (const valarray<T>&);

   >     template<class T> valarray<T> atan2(const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<T> atan2(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> atan2(const Ttypename valarray<T>::value_type&, const valarray<T>&);

   >     template<class T> valarray<T> cos (const valarray<T>&);
   >     template<class T> valarray<T> cosh (const valarray<T>&);
   >     template<class T> valarray<T> exp (const valarray<T>&);
   >     template<class T> valarray<T> log (const valarray<T>&);
   >     template<class T> valarray<T> log10(const valarray<T>&);

   >     template<class T> valarray<T> pow(const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<T> pow(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> pow(const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     […]

2. Edit 28.6.3.1 [valarray.binary] as indicated:

   >     […]
   >     template<class T> valarray<T> operator* (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator* (const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<T> operator/ (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator/ (const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<T> operator% (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator% (const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<T> operator+ (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator+ (const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<T> operator- (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator- (const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<T> operator^ (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator^ (const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<T> operator& (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator& (const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<T> operator| (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator| (const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<T> operator<<(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator<<(const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<T> operator>>(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> operator>>(const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     […]

3. Edit 28.6.3.2 [valarray.comparison] as indicated:

   >     […]
   >     template<class T> valarray<bool> operator==(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator==(const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<bool> operator!=(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator!=(const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<bool> operator< (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator< (const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<bool> operator> (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator> (const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<bool> operator<=(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator<=(const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<bool> operator>=(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator>=(const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<bool> operator&&(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator&&(const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<bool> operator||(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<bool> operator||(const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     […]

4. Edit 28.6.3.3 [valarray.transcend] as indicated:

   >     template<class T> valarray<T> abs (const valarray<T>&);
   >     template<class T> valarray<T> acos (const valarray<T>&);
   >     template<class T> valarray<T> asin (const valarray<T>&);
   >     template<class T> valarray<T> atan (const valarray<T>&);
   >     template<class T> valarray<T> atan2(const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<T> atan2(const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> atan2(const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     template<class T> valarray<T> cos (const valarray<T>&);
   >     template<class T> valarray<T> cosh (const valarray<T>&);
   >     template<class T> valarray<T> exp (const valarray<T>&);
   >     template<class T> valarray<T> log (const valarray<T>&);
   >     template<class T> valarray<T> log10(const valarray<T>&);
   >     template<class T> valarray<T> pow (const valarray<T>&, const valarray<T>&);
   >     template<class T> valarray<T> pow (const valarray<T>&, const Ttypename valarray<T>::value_type&);
   >     template<class T> valarray<T> pow (const Ttypename valarray<T>::value_type&, const valarray<T>&);
   >     […]