On 11/19/18 6:13 AM, Jonathan Wakely wrote:
On 16/11/18 19:39 -0500, Ed Smith-Rowland wrote:
@@ -322,67 +323,43 @@
  //@{
  ///  Return new complex value @a x plus @a y.
  template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
    operator+(const complex<_Tp>& __x, const complex<_Tp>& __y)
-    {
-      complex<_Tp> __r = __x;
-      __r += __y;
-      return __r;
-    }
+    { return complex<_Tp>(__x.real() + __y.real(), __x.imag() + __y.imag()); }

Is this change (and all the similar ones) really needed?

Doesn't the fact that all the constructors and member operators of
std::complex mean that the original definition is also valid in a
constexpr function?
These changes are rolled back. Sorry.
@@ -1163,50 +1143,43 @@
#endif

      template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
        operator=(const complex<_Tp>&  __z)
    {
-      __real__ _M_value = __z.real();
-      __imag__ _M_value = __z.imag();
+      _M_value = __z.__rep();

These changes look OK, but I wonder if we shouldn't ask the compiler
to make it possible to use __real__ and __imag__ in constexpr
functions instead.

I assume it doesn't, and that's why you made this change. But if it
Just Worked, and the other changes I commented on above are also
unnecessary, then this patch would *mostly* just be adding
_GLIBCXX20_CONSTEXPR which is OK for stage 3 (as it doesn't affect any
dialects except C++2a).

Yes, this is the issue.  I agree that constexpr _real__, __imag__would be better.

Do you have any idea where this change would be?  I grepped around a little and couldn't figure it out.  if you don't I'll look more.

Actually, looking at constexpr.c it looks like the old way ought to work...

OK, plain assignment works but not the others.  Interesting.


@@ -1872,7 +1831,7 @@
    { return _Tp(); }

  template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type
+    _GLIBCXX_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type

This should be _GLIBCXX20_CONSTEXPR.
Done.
Index: testsuite/26_numerics/complex/comparison_operators/more_constexpr.cc
===================================================================
--- testsuite/26_numerics/complex/comparison_operators/more_constexpr.cc (nonexistent) +++ testsuite/26_numerics/complex/comparison_operators/more_constexpr.cc (working copy)
@@ -0,0 +1,51 @@
+// { dg-do compile { target c++2a } }

All the tests with { target c++2a} should also have:

// { dg-options "-std=gnu++2a" }

Because otherwise they are skipped by default, and only get run when
RUNTESTFLAGS explicitly includes something like
--target_board=unix/-std=gnu++2a

The dg-options needs to come first, or it doesn't apply before the
check for { target c++2a }.

Thank you, done.

Updated patch attached.  I'd like to understand why

    __real__ _M_value += __z.real();

doesn't work though.

Ed


Index: include/std/complex
===================================================================
--- include/std/complex (revision 266251)
+++ include/std/complex (working copy)
@@ -70,10 +70,11 @@
   ///  Return phase angle of @a z.
   template<typename _Tp> _Tp arg(const complex<_Tp>&);
   ///  Return @a z magnitude squared.
-  template<typename _Tp> _Tp norm(const complex<_Tp>&);
+  template<typename _Tp> _Tp _GLIBCXX20_CONSTEXPR norm(const complex<_Tp>&);
 
   ///  Return complex conjugate of @a z.
-  template<typename _Tp> complex<_Tp> conj(const complex<_Tp>&);
+  template<typename _Tp>
+    _GLIBCXX20_CONSTEXPR complex<_Tp> conj(const complex<_Tp>&);
   ///  Return complex with magnitude @a rho and angle @a theta.
   template<typename _Tp> complex<_Tp> polar(const _Tp&, const _Tp& = 0);
 
@@ -169,18 +170,18 @@
 
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // DR 387. std::complex over-encapsulated.
-      void
+      _GLIBCXX20_CONSTEXPR void
       real(_Tp __val) { _M_real = __val; }
 
-      void
+      _GLIBCXX20_CONSTEXPR void
       imag(_Tp __val) { _M_imag = __val; }
 
       /// Assign a scalar to this complex number.
-      complex<_Tp>& operator=(const _Tp&);
+      _GLIBCXX20_CONSTEXPR complex<_Tp>& operator=(const _Tp&);
 
       /// Add a scalar to this complex number.
       // 26.2.5/1
-      complex<_Tp>&
+      _GLIBCXX20_CONSTEXPR complex<_Tp>&
       operator+=(const _Tp& __t)
       {
        _M_real += __t;
@@ -189,7 +190,7 @@
 
       /// Subtract a scalar from this complex number.
       // 26.2.5/3
-      complex<_Tp>&
+      _GLIBCXX20_CONSTEXPR complex<_Tp>&
       operator-=(const _Tp& __t)
       {
        _M_real -= __t;
@@ -197,30 +198,30 @@
       }
 
       /// Multiply this complex number by a scalar.
-      complex<_Tp>& operator*=(const _Tp&);
+      _GLIBCXX20_CONSTEXPR complex<_Tp>& operator*=(const _Tp&);
       /// Divide this complex number by a scalar.
-      complex<_Tp>& operator/=(const _Tp&);
+      _GLIBCXX20_CONSTEXPR complex<_Tp>& operator/=(const _Tp&);
 
       // Let the compiler synthesize the copy assignment operator
 #if __cplusplus >= 201103L
-      complex& operator=(const complex&) = default;
+      _GLIBCXX20_CONSTEXPR complex& operator=(const complex&) = default;
 #endif
 
       /// Assign another complex number to this one.
       template<typename _Up>
-        complex<_Tp>& operator=(const complex<_Up>&);
+        _GLIBCXX20_CONSTEXPR complex<_Tp>& operator=(const complex<_Up>&);
       /// Add another complex number to this one.
       template<typename _Up>
-        complex<_Tp>& operator+=(const complex<_Up>&);
+        _GLIBCXX20_CONSTEXPR complex<_Tp>& operator+=(const complex<_Up>&);
       /// Subtract another complex number from this one.
       template<typename _Up>
-        complex<_Tp>& operator-=(const complex<_Up>&);
+        _GLIBCXX20_CONSTEXPR complex<_Tp>& operator-=(const complex<_Up>&);
       /// Multiply this complex number by another.
       template<typename _Up>
-        complex<_Tp>& operator*=(const complex<_Up>&);
+        _GLIBCXX20_CONSTEXPR complex<_Tp>& operator*=(const complex<_Up>&);
       /// Divide this complex number by another.
       template<typename _Up>
-        complex<_Tp>& operator/=(const complex<_Up>&);
+        _GLIBCXX20_CONSTEXPR complex<_Tp>& operator/=(const complex<_Up>&);
 
       _GLIBCXX_CONSTEXPR complex __rep() const
       { return *this; }
@@ -231,7 +232,7 @@
     };
 
   template<typename _Tp>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator=(const _Tp& __t)
     {
      _M_real = __t;
@@ -241,7 +242,7 @@
 
   // 26.2.5/5
   template<typename _Tp>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator*=(const _Tp& __t)
     {
       _M_real *= __t;
@@ -251,7 +252,7 @@
 
   // 26.2.5/7
   template<typename _Tp>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator/=(const _Tp& __t)
     {
       _M_real /= __t;
@@ -261,7 +262,7 @@
 
   template<typename _Tp>
     template<typename _Up>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator=(const complex<_Up>& __z)
     {
       _M_real = __z.real();
@@ -272,7 +273,7 @@
   // 26.2.5/9
   template<typename _Tp>
     template<typename _Up>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator+=(const complex<_Up>& __z)
     {
       _M_real += __z.real();
@@ -283,7 +284,7 @@
   // 26.2.5/11
   template<typename _Tp>
     template<typename _Up>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator-=(const complex<_Up>& __z)
     {
       _M_real -= __z.real();
@@ -295,7 +296,7 @@
   // XXX: This is a grammar school implementation.
   template<typename _Tp>
     template<typename _Up>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator*=(const complex<_Up>& __z)
     {
       const _Tp __r = _M_real * __z.real() - _M_imag * __z.imag();
@@ -308,7 +309,7 @@
   // XXX: This is a grammar school implementation.
   template<typename _Tp>
     template<typename _Up>
-    complex<_Tp>&
+    _GLIBCXX20_CONSTEXPR complex<_Tp>&
     complex<_Tp>::operator/=(const complex<_Up>& __z)
     {
       const _Tp __r =  _M_real * __z.real() + _M_imag * __z.imag();
@@ -322,7 +323,7 @@
   //@{
   ///  Return new complex value @a x plus @a y.
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator+(const complex<_Tp>& __x, const complex<_Tp>& __y)
     {
       complex<_Tp> __r = __x;
@@ -331,7 +332,7 @@
     }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator+(const complex<_Tp>& __x, const _Tp& __y)
     {
       complex<_Tp> __r = __x;
@@ -340,7 +341,7 @@
     }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator+(const _Tp& __x, const complex<_Tp>& __y)
     {
       complex<_Tp> __r = __y;
@@ -352,7 +353,7 @@
   //@{
   ///  Return new complex value @a x minus @a y.
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator-(const complex<_Tp>& __x, const complex<_Tp>& __y)
     {
       complex<_Tp> __r = __x;
@@ -361,7 +362,7 @@
     }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator-(const complex<_Tp>& __x, const _Tp& __y)
     {
       complex<_Tp> __r = __x;
@@ -370,11 +371,11 @@
     }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator-(const _Tp& __x, const complex<_Tp>& __y)
     {
-      complex<_Tp> __r(__x, -__y.imag());
-      __r -= __y.real();
+      complex<_Tp> __r = -__y;
+      __r += __x;
       return __r;
     }
   //@}
@@ -382,7 +383,7 @@
   //@{
   ///  Return new complex value @a x times @a y.
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator*(const complex<_Tp>& __x, const complex<_Tp>& __y)
     {
       complex<_Tp> __r = __x;
@@ -391,7 +392,7 @@
     }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator*(const complex<_Tp>& __x, const _Tp& __y)
     {
       complex<_Tp> __r = __x;
@@ -400,7 +401,7 @@
     }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator*(const _Tp& __x, const complex<_Tp>& __y)
     {
       complex<_Tp> __r = __y;
@@ -412,7 +413,7 @@
   //@{
   ///  Return new complex value @a x divided by @a y.
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator/(const complex<_Tp>& __x, const complex<_Tp>& __y)
     {
       complex<_Tp> __r = __x;
@@ -421,7 +422,7 @@
     }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator/(const complex<_Tp>& __x, const _Tp& __y)
     {
       complex<_Tp> __r = __x;
@@ -430,7 +431,7 @@
     }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator/(const _Tp& __x, const complex<_Tp>& __y)
     {
       complex<_Tp> __r = __x;
@@ -441,15 +442,15 @@
 
   ///  Return @a x.
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator+(const complex<_Tp>& __x)
     { return __x; }
 
   ///  Return complex negation of @a x.
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     operator-(const complex<_Tp>& __x)
-    {  return complex<_Tp>(-__x.real(), -__x.imag()); }
+    { return complex<_Tp>(-__x.real(), -__x.imag()); }
 
   //@{
   ///  Return true if @a x is equal to @a y.
@@ -658,7 +659,7 @@
     struct _Norm_helper
     {
       template<typename _Tp>
-        static inline _Tp _S_do_it(const complex<_Tp>& __z)
+        static inline _GLIBCXX_CONSTEXPR _Tp _S_do_it(const complex<_Tp>& __z)
         {
           const _Tp __x = __z.real();
           const _Tp __y = __z.imag();
@@ -670,15 +671,18 @@
     struct _Norm_helper<true>
     {
       template<typename _Tp>
-        static inline _Tp _S_do_it(const complex<_Tp>& __z)
+        static inline _GLIBCXX_CONSTEXPR _Tp _S_do_it(const complex<_Tp>& __z)
         {
-          _Tp __res = std::abs(__z);
-          return __res * __res;
+          //_Tp __res = std::abs(__z);
+          //return __res * __res;
+          const _Tp __x = __z.real();
+          const _Tp __y = __z.imag();
+          return __x * __x + __y * __y;
         }
     };
 
   template<typename _Tp>
-    inline _Tp
+    inline _GLIBCXX20_CONSTEXPR _Tp
     norm(const complex<_Tp>& __z)
     {
       return _Norm_helper<__is_floating<_Tp>::__value
@@ -694,7 +698,7 @@
     }
 
   template<typename _Tp>
-    inline complex<_Tp>
+    inline _GLIBCXX20_CONSTEXPR complex<_Tp>
     conj(const complex<_Tp>& __z)
     { return complex<_Tp>(__z.real(), -__z.imag()); }
 
@@ -1115,13 +1119,13 @@
 
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // DR 387. std::complex over-encapsulated.
-      void
+      _GLIBCXX20_CONSTEXPR void
       real(float __val) { __real__ _M_value = __val; }
 
-      void
+      _GLIBCXX20_CONSTEXPR void
       imag(float __val) { __imag__ _M_value = __val; }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator=(float __f)
       {
        _M_value = __f;
@@ -1128,7 +1132,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator+=(float __f)
       {
        _M_value += __f;
@@ -1135,7 +1139,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator-=(float __f)
       {
        _M_value -= __f;
@@ -1142,7 +1146,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator*=(float __f)
       {
        _M_value *= __f;
@@ -1149,7 +1153,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator/=(float __f)
       {
        _M_value /= __f;
@@ -1163,7 +1167,7 @@
 #endif
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator=(const complex<_Tp>&  __z)
        {
          __real__ _M_value = __z.real();
@@ -1172,41 +1176,35 @@
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator+=(const complex<_Tp>& __z)
        {
-         __real__ _M_value += __z.real();
-         __imag__ _M_value += __z.imag();
+         _M_value += __z.__rep();
          return *this;
        }
 
       template<class _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator-=(const complex<_Tp>& __z)
        {
-         __real__ _M_value -= __z.real();
-         __imag__ _M_value -= __z.imag();
+         _M_value -= __z.__rep();
          return *this;
        }
 
       template<class _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator*=(const complex<_Tp>& __z)
        {
-         _ComplexT __t;
-         __real__ __t = __z.real();
-         __imag__ __t = __z.imag();
+         const _ComplexT __t = __z.__rep();
          _M_value *= __t;
          return *this;
        }
 
       template<class _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator/=(const complex<_Tp>& __z)
        {
-         _ComplexT __t;
-         __real__ __t = __z.real();
-         __imag__ __t = __z.imag();
+         const _ComplexT __t = __z.__rep();
          _M_value /= __t;
          return *this;
        }
@@ -1268,13 +1266,13 @@
 
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // DR 387. std::complex over-encapsulated.
-      void
+      _GLIBCXX20_CONSTEXPR void
       real(double __val) { __real__ _M_value = __val; }
 
-      void
+      _GLIBCXX20_CONSTEXPR void
       imag(double __val) { __imag__ _M_value = __val; }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator=(double __d)
       {
        _M_value = __d;
@@ -1281,7 +1279,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator+=(double __d)
       {
        _M_value += __d;
@@ -1288,7 +1286,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator-=(double __d)
       {
        _M_value -= __d;
@@ -1295,7 +1293,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator*=(double __d)
       {
        _M_value *= __d;
@@ -1302,7 +1300,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator/=(double __d)
       {
        _M_value /= __d;
@@ -1315,50 +1313,43 @@
 #endif
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator=(const complex<_Tp>& __z)
        {
-         __real__ _M_value = __z.real();
-         __imag__ _M_value = __z.imag();
+         _M_value = __z.__rep();
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator+=(const complex<_Tp>& __z)
        {
-         __real__ _M_value += __z.real();
-         __imag__ _M_value += __z.imag();
+         _M_value += __z.__rep();
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator-=(const complex<_Tp>& __z)
        {
-         __real__ _M_value -= __z.real();
-         __imag__ _M_value -= __z.imag();
+         _M_value -= __z.__rep();
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator*=(const complex<_Tp>& __z)
        {
-         _ComplexT __t;
-         __real__ __t = __z.real();
-         __imag__ __t = __z.imag();
+         const _ComplexT __t = __z.__rep();
          _M_value *= __t;
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator/=(const complex<_Tp>& __z)
        {
-         _ComplexT __t;
-         __real__ __t = __z.real();
-         __imag__ __t = __z.imag();
+         const _ComplexT __t = __z.__rep();
          _M_value /= __t;
          return *this;
        }
@@ -1422,13 +1413,13 @@
 
       // _GLIBCXX_RESOLVE_LIB_DEFECTS
       // DR 387. std::complex over-encapsulated.
-      void
+      _GLIBCXX20_CONSTEXPR void
       real(long double __val) { __real__ _M_value = __val; }
 
-      void
+      _GLIBCXX20_CONSTEXPR void
       imag(long double __val) { __imag__ _M_value = __val; }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator=(long double __r)
       {
        _M_value = __r;
@@ -1435,7 +1426,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator+=(long double __r)
       {
        _M_value += __r;
@@ -1442,7 +1433,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator-=(long double __r)
       {
        _M_value -= __r;
@@ -1449,7 +1440,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator*=(long double __r)
       {
        _M_value *= __r;
@@ -1456,7 +1447,7 @@
        return *this;
       }
 
-      complex&
+      _GLIBCXX20_CONSTEXPR complex&
       operator/=(long double __r)
       {
        _M_value /= __r;
@@ -1469,50 +1460,43 @@
 #endif
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
         operator=(const complex<_Tp>& __z)
        {
-         __real__ _M_value = __z.real();
-         __imag__ _M_value = __z.imag();
+         _M_value = __z.__rep();
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
        operator+=(const complex<_Tp>& __z)
        {
-         __real__ _M_value += __z.real();
-         __imag__ _M_value += __z.imag();
+         _M_value += __z.__rep();
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
        operator-=(const complex<_Tp>& __z)
        {
-         __real__ _M_value -= __z.real();
-         __imag__ _M_value -= __z.imag();
+         _M_value -= __z.__rep();
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
        operator*=(const complex<_Tp>& __z)
        {
-         _ComplexT __t;
-         __real__ __t = __z.real();
-         __imag__ __t = __z.imag();
+         const _ComplexT __t = __z.__rep();
          _M_value *= __t;
          return *this;
        }
 
       template<typename _Tp>
-        complex&
+        _GLIBCXX20_CONSTEXPR complex&
        operator/=(const complex<_Tp>& __z)
        {
-         _ComplexT __t;
-         __real__ __t = __z.real();
-         __imag__ __t = __z.imag();
+         const _ComplexT __t = __z.__rep();
          _M_value /= __t;
          return *this;
        }
@@ -1872,7 +1856,7 @@
     { return _Tp(); }
 
   template<typename _Tp>
-    inline typename __gnu_cxx::__promote<_Tp>::__type
+    _GLIBCXX20_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type
     norm(_Tp __x)
     {
       typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
@@ -1911,7 +1895,8 @@
 
   // Forward declarations.
   // DR 781.
-  template<typename _Tp> std::complex<_Tp> proj(const std::complex<_Tp>&);
+  template<typename _Tp>
+    std::complex<_Tp> proj(const std::complex<_Tp>&);
 
   template<typename _Tp>
     std::complex<_Tp>
@@ -1957,7 +1942,8 @@
     }
 
   template<typename _Tp>
-    inline std::complex<typename __gnu_cxx::__promote<_Tp>::__type>
+    inline _GLIBCXX20_CONSTEXPR
+       std::complex<typename __gnu_cxx::__promote<_Tp>::__type>
     conj(_Tp __x)
     {
       typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
Index: testsuite/26_numerics/complex/comparison_operators/more_constexpr.cc
===================================================================
--- testsuite/26_numerics/complex/comparison_operators/more_constexpr.cc        
(nonexistent)
+++ testsuite/26_numerics/complex/comparison_operators/more_constexpr.cc        
(working copy)
@@ -0,0 +1,52 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <complex>
+#include <testsuite_common_types.h>
+
+template<bool ok>
+  struct thing
+  { };
+
+// 
+template<typename _Tp>
+  void
+  test_comparison()
+  {
+    constexpr std::complex<_Tp> a{1.1, 2.2};
+    constexpr std::complex<_Tp> b{3.3, 4.4};
+    if constexpr (a == b)
+      auto c [[maybe_unused]] = a + b;
+    if constexpr (a != b)
+      auto c [[maybe_unused]] = a - b;
+
+    thing<a == b> thing1 [[maybe_unused]];
+    thing<a != b> thing2 [[maybe_unused]];
+  }
+
+int
+main()
+{
+  test_comparison<float>();
+  test_comparison<double>();
+  test_comparison<long double>();
+
+  return 0;
+}
Index: testsuite/26_numerics/complex/operators/more_constexpr.cc
===================================================================
--- testsuite/26_numerics/complex/operators/more_constexpr.cc   (nonexistent)
+++ testsuite/26_numerics/complex/operators/more_constexpr.cc   (working copy)
@@ -0,0 +1,62 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <complex>
+#include <testsuite_common_types.h>
+
+namespace __gnu_test
+{
+  // Test constexpr symmetric complex @ real, real @ complex, complex @ 
complex.
+  template<typename _Tp>
+    void
+    test_operators()
+    {
+      constexpr std::complex<_Tp> a{1, 2};
+      constexpr std::complex<_Tp> b{3, 4};
+      constexpr _Tp c = 5;
+
+      constexpr auto w [[maybe_unused]] = +a;
+      constexpr auto z [[maybe_unused]] = -a;
+
+      constexpr auto apc [[maybe_unused]] = a + c;
+      constexpr auto amc [[maybe_unused]] = a - c;
+      constexpr auto atc [[maybe_unused]] = a * c;
+      constexpr auto adc [[maybe_unused]] = a / c;
+
+      constexpr auto cpa [[maybe_unused]] = c + a;
+      constexpr auto cma [[maybe_unused]] = c - a;
+      constexpr auto cta [[maybe_unused]] = c * a;
+      constexpr auto cda [[maybe_unused]] = c / a;
+
+      constexpr auto apb [[maybe_unused]] = a + b;
+      constexpr auto amb [[maybe_unused]] = a - b;
+      constexpr auto atb [[maybe_unused]] = a * b;
+      constexpr auto adb [[maybe_unused]] = a / b;
+    }
+}
+
+int main()
+{
+  __gnu_test::test_operators<float>();
+  __gnu_test::test_operators<double>();
+  __gnu_test::test_operators<long double>();
+
+  return 0;
+}
Index: testsuite/26_numerics/complex/requirements/more_constexpr.cc
===================================================================
--- testsuite/26_numerics/complex/requirements/more_constexpr.cc        
(nonexistent)
+++ testsuite/26_numerics/complex/requirements/more_constexpr.cc        
(working copy)
@@ -0,0 +1,171 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <complex>
+#include <testsuite_common_types.h>
+
+namespace __gnu_test
+{
+
+  // Test constexpr real(val) imag(val).
+  template<typename _Tp, const int _Val = 42>
+    inline void
+    set_real(std::complex<_Tp>& a)
+    { a.real(_Val); }
+
+  template<typename _Tp, const int _Val = 42>
+    inline void
+    set_imag(std::complex<_Tp>& a)
+    { a.imag(_Val); }
+
+  template<typename _Tp>
+    void
+    test_members()
+    {
+      constexpr std::complex<_Tp> a{1.1, 2.2};
+
+      std::complex<_Tp> z = a;
+
+      set_real<_Tp, 33>(z);
+      set_imag<_Tp, 44>(z);
+    }
+
+  // Test operators @=complex and @=real.
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    sum(const std::complex<_Tp>& z, const std::complex<_Up>& w)
+    {
+      std::complex<_Tp> x = z;
+      x += w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    sum(const std::complex<_Tp>& z, _Up w)
+    {
+      std::complex<_Tp> x = z;
+      x += w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    dif(const std::complex<_Tp>& z, const std::complex<_Up>& w)
+    {
+      std::complex<_Tp> x = z;
+      x -= w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    dif(const std::complex<_Tp>& z, _Up w)
+    {
+      std::complex<_Tp> x = z;
+      x -= w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    prod(const std::complex<_Tp>& z, const std::complex<_Up>& w)
+    {
+      std::complex<_Tp> x = z;
+      x *= w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    prod(const std::complex<_Tp>& z, _Up w)
+    {
+      std::complex<_Tp> x = z;
+      x *= w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    quot(const std::complex<_Tp>& z, const std::complex<_Up>& w)
+    {
+      std::complex<_Tp> x = z;
+      x /= w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    constexpr std::complex<_Tp>
+    quot(const std::complex<_Tp>& z, _Up w)
+    {
+      std::complex<_Tp> x = z;
+      x /= w;
+      return x;
+    }
+
+  template<typename _Tp, typename _Up>
+    void
+    test_operator_members()
+    {
+      constexpr std::complex<_Tp> a{10, 20};
+      constexpr std::complex<_Up> b{6, 8};
+      constexpr _Up c{10};
+
+      constexpr auto apc = sum(a, c);
+      static_assert(apc == std::complex<_Tp>{20, 20});
+      constexpr auto amc = dif(a, c);
+      static_assert(amc == std::complex<_Tp>{0, 20});
+      constexpr auto atc = prod(a, c);
+      static_assert(atc == std::complex<_Tp>{100, 200});
+      constexpr auto adc = quot(a, c);
+      static_assert(adc == std::complex<_Tp>{1, 2});
+
+      constexpr auto apb = sum(a, b);
+      static_assert(apb == std::complex<_Tp>{16, 28});
+      constexpr auto amb = dif(a, b);
+      static_assert(amb == std::complex<_Tp>{4, 12});
+      constexpr auto atb = prod(a, b);
+      static_assert(atb == std::complex<_Tp>{-100, 200});
+      constexpr auto adb = quot(a, b);
+      static_assert(adb == std::complex<_Tp>{11/_Tp{5}, 2/_Tp{5}});
+    }
+}
+
+int main()
+{
+  __gnu_test::test_members<float>();
+  __gnu_test::test_members<double>();
+  __gnu_test::test_members<long double>();
+
+  __gnu_test::test_operator_members<float, float>();
+  __gnu_test::test_operator_members<float, double>();
+  __gnu_test::test_operator_members<float, long double>();
+  __gnu_test::test_operator_members<double, float>();
+  __gnu_test::test_operator_members<double, double>();
+  __gnu_test::test_operator_members<double, long double>();
+  __gnu_test::test_operator_members<long double, float>();
+  __gnu_test::test_operator_members<long double, double>();
+  __gnu_test::test_operator_members<long double, long double>();
+
+  // Test primary template.
+  __gnu_test::test_operator_members<__float128, __float128>();
+
+  return 0;
+}
Index: testsuite/26_numerics/complex/value_operations/more_constexpr.cc
===================================================================
--- testsuite/26_numerics/complex/value_operations/more_constexpr.cc    
(nonexistent)
+++ testsuite/26_numerics/complex/value_operations/more_constexpr.cc    
(working copy)
@@ -0,0 +1,59 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <complex>
+#include <testsuite_common_types.h>
+
+namespace __gnu_test
+{
+  struct constexpr_functions
+  {
+    template<typename _Ttesttype>
+      void
+      operator()()
+      {
+       struct _Concept
+       {
+         void __constraint()
+         { 
+           typedef typename _Ttesttype::_ComplexT _ComplexT;
+           constexpr _ComplexT cc = { 1.1 };
+           constexpr _Ttesttype a(cc);
+           constexpr auto v1 [[maybe_unused]] = norm(a);
+           constexpr auto v2 [[maybe_unused]] = conj(a);
+         }
+       };
+
+       _Concept c;
+       c.__constraint();
+      }
+  };
+}
+
+int main()
+{
+  __gnu_test::constexpr_functions test;
+
+  test.operator()<std::complex<float>>();
+  test.operator()<std::complex<double>>();
+  test.operator()<std::complex<long double>>();
+
+  return 0;
+}
Index: testsuite/26_numerics/headers/complex/synopsis.cc
===================================================================
--- testsuite/26_numerics/headers/complex/synopsis.cc   (revision 266251)
+++ testsuite/26_numerics/headers/complex/synopsis.cc   (working copy)
@@ -28,51 +28,71 @@
 
   // 26.2.6 operators:
   template<class T>
-    complex<T> operator+(const complex<T>&, const complex<T>&);
-  template<class T> complex<T> operator+(const complex<T>&, const T&);
-  template<class T> complex<T> operator+(const T&, const complex<T>&);
-  template<class T> complex<T> operator-
+    _GLIBCXX20_CONSTEXPR complex<T>
+    operator+(const complex<T>&, const complex<T>&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator+(const complex<T>&, const T&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator+(const T&, const complex<T>&);
+
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T>
+    operator-(const complex<T>&, const complex<T>&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator-(const complex<T>&, const T&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator-(const T&, const complex<T>&);
+
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator*
     (const complex<T>&, const complex<T>&);
-  template<class T> complex<T> operator-(const complex<T>&, const T&);
-  template<class T> complex<T> operator-(const T&, const complex<T>&);
-  template<class T> complex<T> operator*
-    (const complex<T>&, const complex<T>&);
-  template<class T> complex<T> operator*(const complex<T>&, const T&);
-  template<class T> complex<T> operator*(const T&, const complex<T>&);
-  template<class T> complex<T> operator/
-    (const complex<T>&, const complex<T>&);
-  template<class T> complex<T> operator/(const complex<T>&, const T&);
-  template<class T> complex<T> operator/(const T&, const complex<T>&);
-  template<class T> complex<T> operator+(const complex<T>&);
-  template<class T> complex<T> operator-(const complex<T>&);
-  template<class T> _GLIBCXX_CONSTEXPR bool operator==
-    (const complex<T>&, const complex<T>&);
-  template<class T> _GLIBCXX_CONSTEXPR bool operator==
-    (const complex<T>&, const T&);
-  template<class T> _GLIBCXX_CONSTEXPR bool operator==
-    (const T&, const complex<T>&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator*(const complex<T>&, const T&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator*(const T&, const complex<T>&);
 
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T>
+    operator/(const complex<T>&, const complex<T>&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator/(const complex<T>&, const T&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator/(const T&, const complex<T>&);
 
-  template<class T> _GLIBCXX_CONSTEXPR bool operator!=
-    (const complex<T>&, const complex<T>&);
-  template<class T> _GLIBCXX_CONSTEXPR bool operator!=
-    (const complex<T>&, const T&);
-  template<class T> _GLIBCXX_CONSTEXPR bool operator!=
-    (const T&, const complex<T>&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator+(const complex<T>&);
+  template<class T>
+    _GLIBCXX20_CONSTEXPR complex<T> operator-(const complex<T>&);
+
+  template<class T>
+    _GLIBCXX_CONSTEXPR bool operator==(const complex<T>&, const complex<T>&);
+  template<class T>
+     _GLIBCXX_CONSTEXPR bool operator==(const complex<T>&, const T&);
+  template<class T>
+    _GLIBCXX_CONSTEXPR bool operator==(const T&, const complex<T>&);
+
+  template<class T>
+    _GLIBCXX_CONSTEXPR bool operator!=(const complex<T>&, const complex<T>&);
+  template<class T>
+    _GLIBCXX_CONSTEXPR bool operator!=(const complex<T>&, const T&);
+  template<class T>
+    _GLIBCXX_CONSTEXPR bool operator!=(const T&, const complex<T>&);
+
   template<class T, class charT, class traits>
-  basic_istream<charT, traits>&
-  operator>>(basic_istream<charT, traits>&, complex<T>&);
+    basic_istream<charT, traits>&
+    operator>>(basic_istream<charT, traits>&, complex<T>&);
   template<class T, class charT, class traits>
-  basic_ostream<charT, traits>&
-  operator<<(basic_ostream<charT, traits>&, const complex<T>&);
+    basic_ostream<charT, traits>&
+    operator<<(basic_ostream<charT, traits>&, const complex<T>&);
 
   // 26.2.7 values:
   template<class T> _GLIBCXX_CONSTEXPR T real(const complex<T>&);
   template<class T> _GLIBCXX_CONSTEXPR T imag(const complex<T>&);
   template<class T> T abs(const complex<T>&);
-  template<class T> T arg(const complex<T>&);
-  template<class T> T norm(const complex<T>&);
-  template<class T> complex<T> conj(const complex<T>&);
+  template<class T> _GLIBCXX20_CONSTEXPR T arg(const complex<T>&);
+  template<class T> _GLIBCXX20_CONSTEXPR T norm(const complex<T>&);
+  template<class T> _GLIBCXX20_CONSTEXPR complex<T> conj(const complex<T>&);
+  template<class T> _GLIBCXX20_CONSTEXPR complex<T> proj(const complex<T>&);
   template<class T> complex<T> polar(const T& rho, const T& theta);
 
   // 26.2.8 transcendentals:

Reply via email to