mclow.lists created this revision. This patch implements most of https://wg21.link/P0451r1 - the notable exception being division. The current implementation of complex division in libc++ uses `logb`, `fmax`, and a couple of other primitives that are not constexpr. The paper has some approaches for dealing with this, but I haven't implemented those yet. I wanted to get all the mechanical bits out first.
Note that there are tests for division being constexpr; they currently fail. https://reviews.llvm.org/D40651 Files: include/complex test/std/numerics/complex.number/complex.member.ops/assignment_scalar.pass.cpp test/std/numerics/complex.number/complex.member.ops/divide_equal_scalar.pass.cpp test/std/numerics/complex.number/complex.member.ops/minus_equal_scalar.pass.cpp test/std/numerics/complex.number/complex.member.ops/plus_equal_scalar.pass.cpp test/std/numerics/complex.number/complex.member.ops/times_equal_scalar.pass.cpp test/std/numerics/complex.number/complex.members/real_imag.pass.cpp test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp test/std/numerics/complex.number/complex.ops/complex_divide_scalar.pass.cpp test/std/numerics/complex.number/complex.ops/complex_minus_complex.pass.cpp test/std/numerics/complex.number/complex.ops/complex_plus_complex.pass.cpp test/std/numerics/complex.number/complex.ops/complex_plus_scalar.pass.cpp test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp test/std/numerics/complex.number/complex.ops/complex_times_scalar.pass.cpp test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp test/std/numerics/complex.number/complex.ops/scalar_minus_complex.pass.cpp test/std/numerics/complex.number/complex.ops/scalar_plus_complex.pass.cpp test/std/numerics/complex.number/complex.ops/scalar_times_complex.pass.cpp test/std/numerics/complex.number/complex.ops/unary_minus.pass.cpp test/std/numerics/complex.number/complex.ops/unary_plus.pass.cpp test/std/numerics/complex.number/complex.value.ops/conj.pass.cpp test/std/numerics/complex.number/complex.value.ops/imag.pass.cpp test/std/numerics/complex.number/complex.value.ops/norm.pass.cpp test/std/numerics/complex.number/complex.value.ops/proj.pass.cpp test/std/numerics/complex.number/complex.value.ops/real.pass.cpp
Index: test/std/numerics/complex.number/complex.value.ops/real.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.value.ops/real.pass.cpp +++ test/std/numerics/complex.number/complex.value.ops/real.pass.cpp @@ -12,16 +12,30 @@ // template<class T> // T // real(const complex<T>& x); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> +TEST_CONSTEXPR bool +constexpr_test() +{ + std::complex<T> z(1.5, 2.5); + return real(z) == 1.5; +} + +template <class T> void test() { std::complex<T> z(1.5, 2.5); assert(real(z) == 1.5); +#if TEST_STD_VER > 17 + static_assert(constexpr_test<T>(), ""); +#endif } int main() Index: test/std/numerics/complex.number/complex.value.ops/proj.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.value.ops/proj.pass.cpp +++ test/std/numerics/complex.number/complex.value.ops/proj.pass.cpp @@ -12,13 +12,24 @@ // template<class T> // complex<T> // proj(const complex<T>& x); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + #include "../cases.h" template <class T> +TEST_CONSTEXPR bool +constexpr_test(const std::complex<T> &z, std::complex<T> x) +{ + return proj(z) == x; +} + + +template <class T> void test(const std::complex<T>& z, std::complex<T> x) { @@ -29,10 +40,24 @@ void test() { - test(std::complex<T>(1, 2), std::complex<T>(1, 2)); - test(std::complex<T>(-1, 2), std::complex<T>(-1, 2)); - test(std::complex<T>(1, -2), std::complex<T>(1, -2)); - test(std::complex<T>(-1, -2), std::complex<T>(-1, -2)); + typedef std::complex<T> C; + + TEST_CONSTEXPR C v12 ( 1, 2); + TEST_CONSTEXPR C v1_2 ( 1, -2); + TEST_CONSTEXPR C v_12 (-1, 2); + TEST_CONSTEXPR C v_1_2(-1, -2); + + test(v12, v12); + test(v_12, v_12); + test(v1_2, v1_2); + test(v_1_2, v_1_2); + +#if TEST_STD_VER > 17 + static_assert(constexpr_test(v12, v12), ""); + static_assert(constexpr_test(v_12, v_12), ""); + static_assert(constexpr_test(v1_2, v1_2), ""); + static_assert(constexpr_test(v_1_2, v_1_2), ""); +#endif } void test_edges() Index: test/std/numerics/complex.number/complex.value.ops/norm.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.value.ops/norm.pass.cpp +++ test/std/numerics/complex.number/complex.value.ops/norm.pass.cpp @@ -12,18 +12,31 @@ // template<class T> // T // norm(const complex<T>& x); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + #include "../cases.h" template <class T> +TEST_CONSTEXPR bool +constexpr_test(const std::complex<T> &z, T expected) +{ + return norm(z) == expected; +} + +template <class T> void test() { - std::complex<T> z(3, 4); + TEST_CONSTEXPR std::complex<T> z(3, 4); assert(norm(z) == 25); +#if TEST_STD_VER > 17 + static_assert(constexpr_test<T>(z, 25), ""); +#endif } void test_edges() Index: test/std/numerics/complex.number/complex.value.ops/imag.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.value.ops/imag.pass.cpp +++ test/std/numerics/complex.number/complex.value.ops/imag.pass.cpp @@ -12,16 +12,30 @@ // template<class T> // T // imag(const complex<T>& x); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> +TEST_CONSTEXPR bool +constexpr_test() +{ + std::complex<T> z(1.5, 2.5); + return imag(z) == 2.5; +} + +template <class T> void test() { std::complex<T> z(1.5, 2.5); assert(imag(z) == 2.5); +#if TEST_STD_VER > 17 + static_assert(constexpr_test<T>(), ""); +#endif } int main() Index: test/std/numerics/complex.number/complex.value.ops/conj.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.value.ops/conj.pass.cpp +++ test/std/numerics/complex.number/complex.value.ops/conj.pass.cpp @@ -12,11 +12,21 @@ // template<class T> // complex<T> // conj(const complex<T>& x); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> +TEST_CONSTEXPR bool +constexpr_test(const std::complex<T> &z, std::complex<T> x) +{ + return conj(z) == x; +} + +template <class T> void test(const std::complex<T>& z, std::complex<T> x) { @@ -27,10 +37,25 @@ void test() { - test(std::complex<T>(1, 2), std::complex<T>(1, -2)); - test(std::complex<T>(-1, 2), std::complex<T>(-1, -2)); - test(std::complex<T>(1, -2), std::complex<T>(1, 2)); - test(std::complex<T>(-1, -2), std::complex<T>(-1, 2)); + typedef std::complex<T> C; + + TEST_CONSTEXPR C v12 ( 1, 2); + TEST_CONSTEXPR C v1_2 ( 1, -2); + TEST_CONSTEXPR C v_12 (-1, 2); + TEST_CONSTEXPR C v_1_2(-1, -2); + + test(v12, v1_2); + test(v_12, v_1_2); + test(v1_2, v12); + test(v_1_2, v_12); + +#if TEST_STD_VER > 17 + static_assert(constexpr_test(v12, v1_2 ), ""); + static_assert(constexpr_test(v_12, v_1_2), ""); + static_assert(constexpr_test(v1_2, v12 ), ""); + static_assert(constexpr_test(v_1_2, v_12 ), ""); +#endif + } int main() Index: test/std/numerics/complex.number/complex.ops/unary_plus.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.ops/unary_plus.pass.cpp +++ test/std/numerics/complex.number/complex.ops/unary_plus.pass.cpp @@ -12,20 +12,34 @@ // template<class T> // complex<T> // operator+(const complex<T>&); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> +TEST_CONSTEXPR bool +constexpr_test(const std::complex<T> &z) +{ + std::complex<T> c = +z; + return c.real() == z.real() && c.imag() == z.imag(); +} + +template <class T> void test() { - std::complex<T> z(1.5, 2.5); + TEST_CONSTEXPR std::complex<T> z(1.5, 2.5); assert(z.real() == 1.5); assert(z.imag() == 2.5); - std::complex<T> c = +z; + TEST_CONSTEXPR std::complex<T> c = +z; assert(c.real() == 1.5); assert(c.imag() == 2.5); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(z), ""); +#endif } int main() Index: test/std/numerics/complex.number/complex.ops/unary_minus.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.ops/unary_minus.pass.cpp +++ test/std/numerics/complex.number/complex.ops/unary_minus.pass.cpp @@ -12,20 +12,34 @@ // template<class T> // complex<T> // operator-(const complex<T>& lhs); +// constexpr in c++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> +TEST_CONSTEXPR bool +constexpr_test(const std::complex<T> &z) +{ + std::complex<T> c = -z; + return c.real() == -z.real() && c.imag() == -z.imag(); +} + +template <class T> void test() { - std::complex<T> z(1.5, 2.5); + TEST_CONSTEXPR std::complex<T> z(1.5, 2.5); assert(z.real() == 1.5); assert(z.imag() == 2.5); - std::complex<T> c = -z; + TEST_CONSTEXPR std::complex<T> c = -z; assert(c.real() == -1.5); assert(c.imag() == -2.5); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(z), ""); +#endif } int main() Index: test/std/numerics/complex.number/complex.ops/scalar_times_complex.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.ops/scalar_times_complex.pass.cpp +++ test/std/numerics/complex.number/complex.ops/scalar_times_complex.pass.cpp @@ -12,10 +12,13 @@ // template<class T> // complex<T> // operator*(const T& lhs, const complex<T>& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> void test(const T& lhs, const std::complex<T>& rhs, std::complex<T> x) @@ -24,13 +27,23 @@ } template <class T> +TEST_CONSTEXPR bool +constexpr_test(const T& lhs, const std::complex<T>& rhs, std::complex<T> x) +{ + return lhs * rhs == x; +} + +template <class T> void test() { - T lhs(1.5); - std::complex<T> rhs(1.5, 2.5); - std::complex<T> x(2.25, 3.75); + TEST_CONSTEXPR T lhs(1.5); + TEST_CONSTEXPR std::complex<T> rhs(1.5, 2.5); + TEST_CONSTEXPR std::complex<T> x(2.25, 3.75); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } int main() Index: test/std/numerics/complex.number/complex.ops/scalar_plus_complex.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.ops/scalar_plus_complex.pass.cpp +++ test/std/numerics/complex.number/complex.ops/scalar_plus_complex.pass.cpp @@ -12,10 +12,13 @@ // template<class T> // complex<T> // operator+(const T& lhs, const complex<T>& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> void test(const T& lhs, const std::complex<T>& rhs, std::complex<T> x) @@ -24,20 +27,33 @@ } template <class T> +TEST_CONSTEXPR bool +constexpr_test(const T& lhs, const std::complex<T>& rhs, std::complex<T> x) +{ + return lhs + rhs == x; +} + +template <class T> void test() { { - T lhs(1.5); - std::complex<T> rhs(3.5, 4.5); - std::complex<T> x(5.0, 4.5); + TEST_CONSTEXPR T lhs(1.5); + TEST_CONSTEXPR std::complex<T> rhs(3.5, 4.5); + TEST_CONSTEXPR std::complex<T> x(5.0, 4.5); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } { - T lhs(1.5); - std::complex<T> rhs(-3.5, 4.5); - std::complex<T> x(-2.0, 4.5); + TEST_CONSTEXPR T lhs(1.5); + TEST_CONSTEXPR std::complex<T> rhs(-3.5, 4.5); + TEST_CONSTEXPR std::complex<T> x(-2.0, 4.5); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } } Index: test/std/numerics/complex.number/complex.ops/scalar_minus_complex.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.ops/scalar_minus_complex.pass.cpp +++ test/std/numerics/complex.number/complex.ops/scalar_minus_complex.pass.cpp @@ -12,10 +12,13 @@ // template<class T> // complex<T> // operator-(const T& lhs, const complex<T>& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> void test(const T& lhs, const std::complex<T>& rhs, std::complex<T> x) @@ -24,20 +27,33 @@ } template <class T> +TEST_CONSTEXPR bool +constexpr_test(const T& lhs, const std::complex<T>& rhs, std::complex<T> x) +{ + return lhs - rhs == x; +} + +template <class T> void test() { { - T lhs(1.5); - std::complex<T> rhs(3.5, 4.5); - std::complex<T> x(-2.0, -4.5); + TEST_CONSTEXPR T lhs(1.5); + TEST_CONSTEXPR std::complex<T> rhs(3.5, 4.5); + TEST_CONSTEXPR std::complex<T> x(-2.0, -4.5); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } { - T lhs(1.5); - std::complex<T> rhs(-3.5, 4.5); - std::complex<T> x(5.0, -4.5); + TEST_CONSTEXPR T lhs(1.5); + TEST_CONSTEXPR std::complex<T> rhs(-3.5, 4.5); + TEST_CONSTEXPR std::complex<T> x(5.0, -4.5); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } } Index: test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp +++ test/std/numerics/complex.number/complex.ops/scalar_divide_complex.pass.cpp @@ -12,10 +12,13 @@ // template<class T> // complex<T> // operator/(const T& lhs, const complex<T>& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> void test(const T& lhs, const std::complex<T>& rhs, std::complex<T> x) @@ -24,13 +27,23 @@ } template <class T> +TEST_CONSTEXPR bool +constexpr_test(const T& lhs, const std::complex<T>& rhs, std::complex<T> x) +{ + return lhs / rhs == x; +} + +template <class T> void test() { - T lhs(-8.5); - std::complex<T> rhs(1.5, 2.5); - std::complex<T> x(-1.5, 2.5); + TEST_CONSTEXPR T lhs(-8.5); + TEST_CONSTEXPR std::complex<T> rhs(1.5, 2.5); + TEST_CONSTEXPR std::complex<T> x(-1.5, 2.5); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } int main() Index: test/std/numerics/complex.number/complex.ops/complex_times_scalar.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.ops/complex_times_scalar.pass.cpp +++ test/std/numerics/complex.number/complex.ops/complex_times_scalar.pass.cpp @@ -12,10 +12,13 @@ // template<class T> // complex<T> // operator*(const complex<T>& lhs, const T& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> void test(const std::complex<T>& lhs, const T& rhs, std::complex<T> x) @@ -24,13 +27,23 @@ } template <class T> +TEST_CONSTEXPR bool +constexpr_test(const std::complex<T>& lhs, const T& rhs, std::complex<T> x) +{ + return lhs * rhs == x; +} + +template <class T> void test() { - std::complex<T> lhs(1.5, 2.5); - T rhs(1.5); - std::complex<T> x(2.25, 3.75); + TEST_CONSTEXPR std::complex<T> lhs(1.5, 2.5); + TEST_CONSTEXPR T rhs(1.5); + TEST_CONSTEXPR std::complex<T> x(2.25, 3.75); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } int main() Index: test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp +++ test/std/numerics/complex.number/complex.ops/complex_times_complex.pass.cpp @@ -12,10 +12,13 @@ // template<class T> // complex<T> // operator*(const complex<T>& lhs, const complex<T>& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + #include "../cases.h" template <class T> @@ -26,13 +29,23 @@ } template <class T> +TEST_CONSTEXPR bool +constexpr_test(const std::complex<T>& lhs, const std::complex<T>& rhs, std::complex<T> x) +{ + return lhs * rhs == x; +} + +template <class T> void test() { - std::complex<T> lhs(1.5, 2.5); - std::complex<T> rhs(1.5, 2.5); - std::complex<T> x(-4.0, 7.5); + TEST_CONSTEXPR std::complex<T> lhs(1.5, 2.5); + TEST_CONSTEXPR std::complex<T> rhs(1.5, 2.5); + TEST_CONSTEXPR std::complex<T> x(-4.0, 7.5); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } // test edges Index: test/std/numerics/complex.number/complex.ops/complex_plus_scalar.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.ops/complex_plus_scalar.pass.cpp +++ test/std/numerics/complex.number/complex.ops/complex_plus_scalar.pass.cpp @@ -12,10 +12,13 @@ // template<class T> // complex<T> // operator+(const complex<T>& lhs, const T& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> void test(const std::complex<T>& lhs, const T& rhs, std::complex<T> x) @@ -24,20 +27,33 @@ } template <class T> +TEST_CONSTEXPR bool +constexpr_test(const std::complex<T>& lhs, const T& rhs, std::complex<T> x) +{ + return lhs + rhs == x; +} + +template <class T> void test() { { - std::complex<T> lhs(1.5, 2.5); - T rhs(3.5); - std::complex<T> x(5.0, 2.5); + TEST_CONSTEXPR std::complex<T> lhs(1.5, 2.5); + TEST_CONSTEXPR T rhs(3.5); + TEST_CONSTEXPR std::complex<T> x(5.0, 2.5); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } { - std::complex<T> lhs(1.5, -2.5); - T rhs(-3.5); - std::complex<T> x(-2.0, -2.5); + TEST_CONSTEXPR std::complex<T> lhs(1.5, -2.5); + TEST_CONSTEXPR T rhs(-3.5); + TEST_CONSTEXPR std::complex<T> x(-2.0, -2.5); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } } Index: test/std/numerics/complex.number/complex.ops/complex_plus_complex.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.ops/complex_plus_complex.pass.cpp +++ test/std/numerics/complex.number/complex.ops/complex_plus_complex.pass.cpp @@ -12,10 +12,13 @@ // template<class T> // complex<T> // operator+(const complex<T>& lhs, const complex<T>& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> void test(const std::complex<T>& lhs, const std::complex<T>& rhs, std::complex<T> x) @@ -24,20 +27,33 @@ } template <class T> +TEST_CONSTEXPR bool +constexpr_test(const std::complex<T>& lhs, const std::complex<T>& rhs, std::complex<T> x) +{ + return lhs + rhs == x; +} + +template <class T> void test() { { - std::complex<T> lhs(1.5, 2.5); - std::complex<T> rhs(3.5, 4.5); - std::complex<T> x(5.0, 7.0); + TEST_CONSTEXPR std::complex<T> lhs(1.5, 2.5); + TEST_CONSTEXPR std::complex<T> rhs(3.5, 4.5); + TEST_CONSTEXPR std::complex<T> x(5.0, 7.0); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } { - std::complex<T> lhs(1.5, -2.5); - std::complex<T> rhs(-3.5, 4.5); - std::complex<T> x(-2.0, 2.0); + TEST_CONSTEXPR std::complex<T> lhs(1.5, -2.5); + TEST_CONSTEXPR std::complex<T> rhs(-3.5, 4.5); + TEST_CONSTEXPR std::complex<T> x(-2.0, 2.0); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } } Index: test/std/numerics/complex.number/complex.ops/complex_minus_complex.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.ops/complex_minus_complex.pass.cpp +++ test/std/numerics/complex.number/complex.ops/complex_minus_complex.pass.cpp @@ -12,10 +12,13 @@ // template<class T> // complex<T> // operator-(const complex<T>& lhs, const complex<T>& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> void test(const std::complex<T>& lhs, const std::complex<T>& rhs, std::complex<T> x) @@ -24,20 +27,33 @@ } template <class T> +TEST_CONSTEXPR bool +constexpr_test(const std::complex<T>& lhs, const std::complex<T>& rhs, std::complex<T> x) +{ + return lhs - rhs == x; +} + +template <class T> void test() { { - std::complex<T> lhs(1.5, 2.5); - std::complex<T> rhs(3.5, 4.5); - std::complex<T> x(-2.0, -2.0); + TEST_CONSTEXPR std::complex<T> lhs(1.5, 2.5); + TEST_CONSTEXPR std::complex<T> rhs(3.5, 4.5); + TEST_CONSTEXPR std::complex<T> x(-2.0, -2.0); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } { - std::complex<T> lhs(1.5, -2.5); - std::complex<T> rhs(-3.5, 4.5); - std::complex<T> x(5.0, -7.0); + TEST_CONSTEXPR std::complex<T> lhs(1.5, -2.5); + TEST_CONSTEXPR std::complex<T> rhs(-3.5, 4.5); + TEST_CONSTEXPR std::complex<T> x(5.0, -7.0); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } } Index: test/std/numerics/complex.number/complex.ops/complex_divide_scalar.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.ops/complex_divide_scalar.pass.cpp +++ test/std/numerics/complex.number/complex.ops/complex_divide_scalar.pass.cpp @@ -12,10 +12,13 @@ // template<class T> // complex<T> // operator/(const complex<T>& lhs, const T& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> void test(const std::complex<T>& lhs, const T& rhs, std::complex<T> x) @@ -24,13 +27,23 @@ } template <class T> +TEST_CONSTEXPR bool +constexpr_test (const std::complex<T>& lhs, const T& rhs, std::complex<T> x) +{ + return lhs / rhs == x; +} + +template <class T> void test() { - std::complex<T> lhs(-4.0, 7.5); - T rhs(2); - std::complex<T> x(-2, 3.75); + TEST_CONSTEXPR std::complex<T> lhs(-4.0, 7.5); + TEST_CONSTEXPR T rhs(2); + TEST_CONSTEXPR std::complex<T> x(-2, 3.75); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } int main() Index: test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp +++ test/std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp @@ -12,10 +12,13 @@ // template<class T> // complex<T> // operator/(const complex<T>& lhs, const complex<T>& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + #include "../cases.h" template <class T> @@ -26,13 +29,23 @@ } template <class T> +TEST_CONSTEXPR bool +constexpr_test(const std::complex<T>& lhs, const std::complex<T>& rhs, std::complex<T> x) +{ + return lhs / rhs == x; +} + +template <class T> void test() { - std::complex<T> lhs(-4.0, 7.5); - std::complex<T> rhs(1.5, 2.5); - std::complex<T> x(1.5, 2.5); + TEST_CONSTEXPR std::complex<T> lhs(-4.0, 7.5); + TEST_CONSTEXPR std::complex<T> rhs(1.5, 2.5); + TEST_CONSTEXPR std::complex<T> x(1.5, 2.5); test(lhs, rhs, x); +#if TEST_STD_VER > 17 + static_assert(constexpr_test(lhs, rhs, x), ""); +#endif } void test_edges() Index: test/std/numerics/complex.number/complex.members/real_imag.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.members/real_imag.pass.cpp +++ test/std/numerics/complex.number/complex.members/real_imag.pass.cpp @@ -18,6 +18,24 @@ #include "test_macros.h" template <class T> +TEST_CONSTEXPR bool +constexpr_real(T val) +{ + std::complex<T> c1{}; + c1.real(val); + return c1.real() == val; +} + +template <class T> +TEST_CONSTEXPR bool +constexpr_imag(T val) +{ + std::complex<T> c1{}; + c1.imag(val); + return c1.imag() == val; +} + +template <class T> void test_constexpr() { @@ -32,6 +50,10 @@ static_assert(c3.real() == 3, ""); static_assert(c3.imag() == 4, ""); #endif +#if TEST_STD_VER > 17 + static_assert(constexpr_real<T>(T(4.7)), "" ); + static_assert(constexpr_imag<T>(T(4.7)), "" ); +#endif } template <class T> Index: test/std/numerics/complex.number/complex.member.ops/times_equal_scalar.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.member.ops/times_equal_scalar.pass.cpp +++ test/std/numerics/complex.number/complex.member.ops/times_equal_scalar.pass.cpp @@ -10,11 +10,21 @@ // <complex> // complex& operator*=(const T& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> +TEST_CONSTEXPR bool +constexpr_test(std::complex<T> lhs, const T& rhs, const std::complex<T>& expected) +{ + return (lhs *= rhs) == expected; +} + +template <class T> void test() { @@ -34,6 +44,12 @@ c *= 1.5; assert(c.real() == -5.0625); assert(c.imag() == 3); + +#if TEST_STD_VER > 17 + TEST_CONSTEXPR std::complex<T> c1{4,-1}; + TEST_CONSTEXPR std::complex<T> c2{8,-2}; + static_assert(constexpr_test(c1, T(2), c2), ""); +#endif } int main() Index: test/std/numerics/complex.number/complex.member.ops/plus_equal_scalar.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.member.ops/plus_equal_scalar.pass.cpp +++ test/std/numerics/complex.number/complex.member.ops/plus_equal_scalar.pass.cpp @@ -10,11 +10,21 @@ // <complex> // complex& operator+=(const T& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> +TEST_CONSTEXPR bool +constexpr_test(std::complex<T> lhs, const T& rhs, const std::complex<T>& expected) +{ + return (lhs += rhs) == expected; +} + +template <class T> void test() { @@ -30,6 +40,12 @@ c += -1.5; assert(c.real() == 1.5); assert(c.imag() == 0); + +#if TEST_STD_VER > 17 + TEST_CONSTEXPR std::complex<T> c1{4,-1}; + TEST_CONSTEXPR std::complex<T> c2{6,-1}; + static_assert(constexpr_test(c1, T(2), c2), ""); +#endif } int main() Index: test/std/numerics/complex.number/complex.member.ops/minus_equal_scalar.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.member.ops/minus_equal_scalar.pass.cpp +++ test/std/numerics/complex.number/complex.member.ops/minus_equal_scalar.pass.cpp @@ -10,11 +10,21 @@ // <complex> // complex& operator-=(const T& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> +TEST_CONSTEXPR bool +constexpr_test(std::complex<T> lhs, const T& rhs, const std::complex<T>& expected) +{ + return (lhs -= rhs) == expected; +} + +template <class T> void test() { @@ -30,6 +40,12 @@ c -= -1.5; assert(c.real() == -1.5); assert(c.imag() == 0); + +#if TEST_STD_VER > 17 + TEST_CONSTEXPR std::complex<T> c1{6,-1}; + TEST_CONSTEXPR std::complex<T> c2{4,-1}; + static_assert(constexpr_test(c1, T(2), c2), ""); +#endif } int main() Index: test/std/numerics/complex.number/complex.member.ops/divide_equal_scalar.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.member.ops/divide_equal_scalar.pass.cpp +++ test/std/numerics/complex.number/complex.member.ops/divide_equal_scalar.pass.cpp @@ -10,11 +10,21 @@ // <complex> // complex& operator/=(const T& rhs); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> +TEST_CONSTEXPR bool +constexpr_test(std::complex<T> lhs, const T& rhs, const std::complex<T>& expected) +{ + return (lhs /= rhs) == expected; +} + +template <class T> void test() { @@ -34,6 +44,12 @@ c /= 0.5; assert(c.real() == -16); assert(c.imag() == 4); + +#if TEST_STD_VER > 17 + TEST_CONSTEXPR std::complex<T> c1{8,-2}; + TEST_CONSTEXPR std::complex<T> c2{4,-1}; + static_assert(constexpr_test(c1, T(2), c2), ""); +#endif } int main() Index: test/std/numerics/complex.number/complex.member.ops/assignment_scalar.pass.cpp =================================================================== --- test/std/numerics/complex.number/complex.member.ops/assignment_scalar.pass.cpp +++ test/std/numerics/complex.number/complex.member.ops/assignment_scalar.pass.cpp @@ -10,11 +10,21 @@ // <complex> // complex& operator= (const T&); +// constexpr in C++20 #include <complex> #include <cassert> +#include "test_macros.h" + template <class T> +TEST_CONSTEXPR bool +constexpr_test(std::complex<T> lhs, const T& rhs) +{ + return (lhs = rhs) == rhs; +} + +template <class T> void test() { @@ -27,6 +37,11 @@ c = -1.5; assert(c.real() == -1.5); assert(c.imag() == 0); + +#if TEST_STD_VER > 17 + TEST_CONSTEXPR std::complex<T> c1{8,-2}; + static_assert(constexpr_test(c1, T(2)), ""); +#endif } int main() Index: include/complex =================================================================== --- include/complex +++ include/complex @@ -33,18 +33,18 @@ void real(T); void imag(T); - complex<T>& operator= (const T&); - complex<T>& operator+=(const T&); - complex<T>& operator-=(const T&); - complex<T>& operator*=(const T&); - complex<T>& operator/=(const T&); + complex<T>& operator= (const T&); // constexpr in C++2a + complex<T>& operator+=(const T&); // constexpr in C++2a + complex<T>& operator-=(const T&); // constexpr in C++2a + complex<T>& operator*=(const T&); // constexpr in C++2a + complex<T>& operator/=(const T&); // constexpr in C++2a complex& operator=(const complex&); - template<class X> complex<T>& operator= (const complex<X>&); - template<class X> complex<T>& operator+=(const complex<X>&); - template<class X> complex<T>& operator-=(const complex<X>&); - template<class X> complex<T>& operator*=(const complex<X>&); - template<class X> complex<T>& operator/=(const complex<X>&); + template<class X> complex<T>& operator= (const complex<X>&); // constexpr in C++2a + template<class X> complex<T>& operator+=(const complex<X>&); // constexpr in C++2a + template<class X> complex<T>& operator-=(const complex<X>&); // constexpr in C++2a + template<class X> complex<T>& operator*=(const complex<X>&); // constexpr in C++2a + template<class X> complex<T>& operator/=(const complex<X>&); // constexpr in C++2a }; template<> @@ -57,23 +57,23 @@ explicit constexpr complex(const complex<double>&); explicit constexpr complex(const complex<long double>&); - constexpr float real() const; - void real(float); - constexpr float imag() const; - void imag(float); + constexpr float real() const; // constexpr in C++14 + void real(float); // constexpr in C++2a + constexpr float imag() const; // constexpr in C++14 + void imag(float); // constexpr in C++2a - complex<float>& operator= (float); - complex<float>& operator+=(float); - complex<float>& operator-=(float); - complex<float>& operator*=(float); - complex<float>& operator/=(float); + complex<float>& operator= (float); // constexpr in C++2a + complex<float>& operator+=(float); // constexpr in C++2a + complex<float>& operator-=(float); // constexpr in C++2a + complex<float>& operator*=(float); // constexpr in C++2a + complex<float>& operator/=(float); // constexpr in C++2a complex<float>& operator=(const complex<float>&); - template<class X> complex<float>& operator= (const complex<X>&); - template<class X> complex<float>& operator+=(const complex<X>&); - template<class X> complex<float>& operator-=(const complex<X>&); - template<class X> complex<float>& operator*=(const complex<X>&); - template<class X> complex<float>& operator/=(const complex<X>&); + template<class X> complex<float>& operator= (const complex<X>&); // constexpr in C++2a + template<class X> complex<float>& operator+=(const complex<X>&); // constexpr in C++2a + template<class X> complex<float>& operator-=(const complex<X>&); // constexpr in C++2a + template<class X> complex<float>& operator*=(const complex<X>&); // constexpr in C++2a + template<class X> complex<float>& operator/=(const complex<X>&); // constexpr in C++2a }; template<> @@ -86,23 +86,23 @@ constexpr complex(const complex<float>&); explicit constexpr complex(const complex<long double>&); - constexpr double real() const; - void real(double); - constexpr double imag() const; - void imag(double); + constexpr double real() const; // constexpr in C++14 + void real(double); // constexpr in C++2a + constexpr double imag() const; // constexpr in C++14 + void imag(double); // constexpr in C++2a - complex<double>& operator= (double); - complex<double>& operator+=(double); - complex<double>& operator-=(double); - complex<double>& operator*=(double); - complex<double>& operator/=(double); + complex<double>& operator= (double); // constexpr in C++2a + complex<double>& operator+=(double); // constexpr in C++2a + complex<double>& operator-=(double); // constexpr in C++2a + complex<double>& operator*=(double); // constexpr in C++2a + complex<double>& operator/=(double); // constexpr in C++2a complex<double>& operator=(const complex<double>&); - template<class X> complex<double>& operator= (const complex<X>&); - template<class X> complex<double>& operator+=(const complex<X>&); - template<class X> complex<double>& operator-=(const complex<X>&); - template<class X> complex<double>& operator*=(const complex<X>&); - template<class X> complex<double>& operator/=(const complex<X>&); + template<class X> complex<double>& operator= (const complex<X>&); // constexpr in C++2a + template<class X> complex<double>& operator+=(const complex<X>&); // constexpr in C++2a + template<class X> complex<double>& operator-=(const complex<X>&); // constexpr in C++2a + template<class X> complex<double>& operator*=(const complex<X>&); // constexpr in C++2a + template<class X> complex<double>& operator/=(const complex<X>&); // constexpr in C++2a }; template<> @@ -115,46 +115,46 @@ constexpr complex(const complex<float>&); constexpr complex(const complex<double>&); - constexpr long double real() const; - void real(long double); - constexpr long double imag() const; - void imag(long double); + constexpr long double real() const; // constexpr in C++14 + void real(long double); // constexpr in C++2a + constexpr long double imag() const; // constexpr in C++14 + void imag(double); // constexpr in C++2a + complex<long double>& operator= (long double); // constexpr in C++2a + complex<long double>& operator+=(long double); // constexpr in C++2a + complex<long double>& operator-=(long double); // constexpr in C++2a + complex<long double>& operator*=(long double); // constexpr in C++2a + complex<long double>& operator/=(long double); // constexpr in C++2a complex<long double>& operator=(const complex<long double>&); - complex<long double>& operator= (long double); - complex<long double>& operator+=(long double); - complex<long double>& operator-=(long double); - complex<long double>& operator*=(long double); - complex<long double>& operator/=(long double); - template<class X> complex<long double>& operator= (const complex<X>&); - template<class X> complex<long double>& operator+=(const complex<X>&); - template<class X> complex<long double>& operator-=(const complex<X>&); - template<class X> complex<long double>& operator*=(const complex<X>&); - template<class X> complex<long double>& operator/=(const complex<X>&); + template<class X> complex<long double>& operator= (const complex<X>&); // constexpr in C++2a + template<class X> complex<long double>& operator+=(const complex<X>&); // constexpr in C++2a + template<class X> complex<long double>& operator-=(const complex<X>&); // constexpr in C++2a + template<class X> complex<long double>& operator*=(const complex<X>&); // constexpr in C++2a + template<class X> complex<long double>& operator/=(const complex<X>&); // constexpr in C++2a }; // 26.3.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-(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> bool operator==(const complex<T>&, const complex<T>&); // constexpr in C++14 -template<class T> bool operator==(const complex<T>&, const T&); // constexpr in C++14 -template<class T> bool operator==(const T&, const complex<T>&); // constexpr in C++14 -template<class T> bool operator!=(const complex<T>&, const complex<T>&); // constexpr in C++14 -template<class T> bool operator!=(const complex<T>&, const T&); // constexpr in C++14 -template<class T> bool operator!=(const T&, const complex<T>&); // constexpr in C++14 +template<class T> complex<T> operator+(const complex<T>&, const complex<T>&); // constexpr in C++2a +template<class T> complex<T> operator+(const complex<T>&, const T&); // constexpr in C++2a +template<class T> complex<T> operator+(const T&, const complex<T>&); // constexpr in C++2a +template<class T> complex<T> operator-(const complex<T>&, const complex<T>&); // constexpr in C++2a +template<class T> complex<T> operator-(const complex<T>&, const T&); // constexpr in C++2a +template<class T> complex<T> operator-(const T&, const complex<T>&); // constexpr in C++2a +template<class T> complex<T> operator*(const complex<T>&, const complex<T>&); // constexpr in C++2a +template<class T> complex<T> operator*(const complex<T>&, const T&); // constexpr in C++2a +template<class T> complex<T> operator*(const T&, const complex<T>&); // constexpr in C++2a +template<class T> complex<T> operator/(const complex<T>&, const complex<T>&); // constexpr in C++2a +template<class T> complex<T> operator/(const complex<T>&, const T&); // constexpr in C++2a +template<class T> complex<T> operator/(const T&, const complex<T>&); // constexpr in C++2a +template<class T> complex<T> operator+(const complex<T>&); // constexpr in C++2a +template<class T> complex<T> operator-(const complex<T>&); // constexpr in C++2a +template<class T> bool operator==(const complex<T>&, const complex<T>&); // constexpr in C++14 +template<class T> bool operator==(const complex<T>&, const T&); // constexpr in C++14 +template<class T> bool operator==(const T&, const complex<T>&); // constexpr in C++14 +template<class T> bool operator!=(const complex<T>&, const complex<T>&); // constexpr in C++14 +template<class T> bool operator!=(const complex<T>&, const T&); // constexpr in C++14 +template<class T> bool operator!=(const T&, const complex<T>&); // constexpr in C++14 template<class T, class charT, class traits> basic_istream<charT, traits>& @@ -185,19 +185,19 @@ template<Integral T> double arg(T); float arg(float); -template<class T> T norm(const complex<T>&); +template<class T> T norm(const complex<T>&); // constexpr in C++2a long double norm(long double); double norm(double); template<Integral T> double norm(T); float norm(float); -template<class T> complex<T> conj(const complex<T>&); +template<class T> complex<T> conj(const complex<T>&); // constexpr in C++2a complex<long double> conj(long double); complex<double> conj(double); template<Integral T> complex<double> conj(T); complex<float> conj(float); -template<class T> complex<T> proj(const complex<T>&); +template<class T> complex<T> proj(const complex<T>&); // constexpr in C++2a complex<long double> proj(long double); complex<double> proj(double); template<Integral T> complex<double> proj(T); @@ -254,7 +254,7 @@ template<class _Tp> class _LIBCPP_TEMPLATE_VIS complex; -template<class _Tp> complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w); +template<class _Tp> _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w); template<class _Tp> complex<_Tp> operator/(const complex<_Tp>& __x, const complex<_Tp>& __y); template<class _Tp> @@ -276,40 +276,58 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 value_type real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 value_type imag() const {return __im_;} - _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} - _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (const value_type& __re) - {__re_ = __re; __im_ = value_type(); return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator+=(const value_type& __re) {__re_ += __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator-=(const value_type& __re) {__re_ -= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator*=(const value_type& __re) {__re_ *= __re; __im_ *= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator/=(const value_type& __re) {__re_ /= __re; __im_ /= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator= (const value_type& __re) {__re_ = __re; __im_ = value_type(); return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator+=(const value_type& __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator-=(const value_type& __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator*=(const value_type& __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator/=(const value_type& __re) {__re_ /= __re; __im_ /= __re; return *this;} - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY // _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -337,40 +355,56 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR float real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR float imag() const {return __im_;} - _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} - _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (float __re) - {__re_ = __re; __im_ = value_type(); return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator+=(float __re) {__re_ += __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator-=(float __re) {__re_ -= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator*=(float __re) {__re_ *= __re; __im_ *= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator/=(float __re) {__re_ /= __re; __im_ /= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator= (float __re) {__re_ = __re; __im_ = value_type(); return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator+=(float __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator-=(float __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator*=(float __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator/=(float __re) {__re_ /= __re; __im_ /= __re; return *this;} - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY // _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -395,40 +429,58 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR double real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR double imag() const {return __im_;} - _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} - _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 void imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (double __re) - {__re_ = __re; __im_ = value_type(); return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator+=(double __re) {__re_ += __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator-=(double __re) {__re_ -= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator*=(double __re) {__re_ *= __re; __im_ *= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator/=(double __re) {__re_ /= __re; __im_ /= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator= (double __re) {__re_ = __re; __im_ = value_type(); return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator+=(double __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator-=(double __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator*=(double __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator/=(double __re) {__re_ /= __re; __im_ /= __re; return *this;} - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY // _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -453,40 +505,58 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR long double real() const {return __re_;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR long double imag() const {return __im_;} - _LIBCPP_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} - _LIBCPP_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + _LIBCPP_INLINE_VISIBILITY void _LIBCPP_CONSTEXPR_AFTER_CXX17 real(value_type __re) {__re_ = __re;} + _LIBCPP_INLINE_VISIBILITY void _LIBCPP_CONSTEXPR_AFTER_CXX17 imag(value_type __im) {__im_ = __im;} - _LIBCPP_INLINE_VISIBILITY complex& operator= (long double __re) - {__re_ = __re; __im_ = value_type(); return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator+=(long double __re) {__re_ += __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator-=(long double __re) {__re_ -= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator*=(long double __re) {__re_ *= __re; __im_ *= __re; return *this;} - _LIBCPP_INLINE_VISIBILITY complex& operator/=(long double __re) {__re_ /= __re; __im_ /= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator= (long double __re) {__re_ = __re; __im_ = value_type(); return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator+=(long double __re) {__re_ += __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator-=(long double __re) {__re_ -= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator*=(long double __re) {__re_ *= __re; __im_ *= __re; return *this;} + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator/=(long double __re) {__re_ /= __re; __im_ /= __re; return *this;} - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator= (const complex<_Xp>& __c) { __re_ = __c.real(); __im_ = __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator+=(const complex<_Xp>& __c) { __re_ += __c.real(); __im_ += __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator-=(const complex<_Xp>& __c) { __re_ -= __c.real(); __im_ -= __c.imag(); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator*=(const complex<_Xp>& __c) { *this = *this * complex(__c.real(), __c.imag()); return *this; } - template<class _Xp> _LIBCPP_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + + template<class _Xp> + _LIBCPP_INLINE_VISIBILITY // _LIBCPP_CONSTEXPR_AFTER_CXX17 + complex& operator/=(const complex<_Xp>& __c) { *this = *this / complex(__c.real(), __c.imag()); return *this; @@ -526,7 +596,7 @@ // 26.3.6 operators: template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator+(const complex<_Tp>& __x, const complex<_Tp>& __y) { @@ -536,7 +606,7 @@ } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator+(const complex<_Tp>& __x, const _Tp& __y) { @@ -546,7 +616,7 @@ } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator+(const _Tp& __x, const complex<_Tp>& __y) { @@ -556,7 +626,7 @@ } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator-(const complex<_Tp>& __x, const complex<_Tp>& __y) { @@ -566,7 +636,7 @@ } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator-(const complex<_Tp>& __x, const _Tp& __y) { @@ -576,7 +646,7 @@ } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator-(const _Tp& __x, const complex<_Tp>& __y) { @@ -586,6 +656,7 @@ } template<class _Tp> +_LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w) { @@ -645,7 +716,7 @@ } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator*(const complex<_Tp>& __x, const _Tp& __y) { @@ -655,7 +726,7 @@ } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator*(const _Tp& __x, const complex<_Tp>& __y) { @@ -665,6 +736,7 @@ } template<class _Tp> +// _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator/(const complex<_Tp>& __z, const complex<_Tp>& __w) { @@ -709,7 +781,7 @@ } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY // _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator/(const complex<_Tp>& __x, const _Tp& __y) { @@ -717,7 +789,7 @@ } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY // _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator/(const _Tp& __x, const complex<_Tp>& __y) { @@ -727,7 +799,7 @@ } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator+(const complex<_Tp>& __x) { @@ -735,7 +807,7 @@ } template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> operator-(const complex<_Tp>& __x) { @@ -906,7 +978,7 @@ // norm template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 _Tp norm(const complex<_Tp>& __c) { @@ -918,7 +990,7 @@ } template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename __libcpp_complex_overload_traits<_Tp>::_ValueType norm(_Tp __re) { @@ -929,7 +1001,7 @@ // conj template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> conj(const complex<_Tp>& __c) { @@ -937,7 +1009,7 @@ } template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename __libcpp_complex_overload_traits<_Tp>::_ComplexType conj(_Tp __re) { @@ -950,7 +1022,7 @@ // proj template<class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 complex<_Tp> proj(const complex<_Tp>& __c) { @@ -961,7 +1033,7 @@ } template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < is_floating_point<_Tp>::value, @@ -975,7 +1047,7 @@ } template <class _Tp> -inline _LIBCPP_INLINE_VISIBILITY +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17 typename enable_if < is_integral<_Tp>::value,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits