Skip to content
Open
18 changes: 18 additions & 0 deletions stl/inc/complex
Original file line number Diff line number Diff line change
Expand Up @@ -1321,6 +1321,23 @@ constexpr complex<long double>::complex(const complex<float>& _Right) noexcept /
constexpr complex<long double>::complex(const complex<double>& _Right) noexcept // strengthened
: _Complex_base<long double, _Lcomplex_value>(_Right.real(), _Right.imag()) {}

#if !_HAS_NONFLOATING_COMPLEX
_EXPORT_STD template <class _Ty>
class complex {
static_assert(false,
"The effect of instantiating the template std::complex for any type other than float, double, or long double "
"is unspecified. The possibility of such instantiation will be removed in a future version. "
Comment on lines +1328 to +1329
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to say "a cv-unqualified floating-point type" (see [complex.numbers.general]/2) which looks more future-proof?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure. I copied that from the deprecation message.

Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The static_assert text says non-floating instantiation "will be removed in a future version", but with _HAS_NONFLOATING_COMPLEX defaulting to 0 this PR effectively removes it now (unless explicitly re-enabled). Please update the wording to accurately describe the current state (e.g., that it is disabled by default / requires opting in) so the error message doesn’t mislead users.

Suggested change
"is unspecified. The possibility of such instantiation will be removed in a future version. "
"is unspecified. Such instantiations are disabled by default in this version. "

Copilot uses AI. Check for mistakes.
"You can define _HAS_NONFLOATING_COMPLEX to 1 to enable such instantiation "
"and define _SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING to suppress its deprecation warning.");
Comment on lines +1325 to +1331
Copy link

Copilot AI Apr 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static_assert(false, ...) inside a class template is non-dependent, so it will fire immediately when is parsed (even if std::complex<T> is never instantiated), effectively breaking all users when _HAS_NONFLOATING_COMPLEX is 0. Make the assertion dependent on _Ty (e.g., assert on a dependent boolean/trait) so the diagnostic is emitted only when std::complex<non-floating> is actually instantiated.

Copilot uses AI. Check for mistakes.

// For deduction, primary template is used, so keeping a couple of constructors around

constexpr complex(const _Ty& = _Ty(), const _Ty& = _Ty()) = delete;
Comment on lines +1333 to +1335
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The deleted deduction-only ctor complex(const _Ty& = _Ty(), const _Ty& = _Ty()) can be ill-formed for some _Ty (e.g. _Ty=void makes const void& invalid; non-default-constructible _Ty makes the default arguments ill-formed). That can cause diagnostics that mask or precede the intended class-scope static_assert message. Consider avoiding _Ty() defaults (e.g. provide separate 1-arg/2-arg deleted overloads without defaults) and/or using a parameter alias that is always a valid object type (e.g. conditional_t<is_void_v<_Ty>, int, _Ty>) so the template remains well-formed and reliably hits the static_assert.

Suggested change
// For deduction, primary template is used, so keeping a couple of constructors around
constexpr complex(const _Ty& = _Ty(), const _Ty& = _Ty()) = delete;
using _Deduction_type = conditional_t<is_void_v<_Ty>, int, _Ty>;
// For deduction, primary template is used, so keeping a couple of constructors around
constexpr complex() = delete;
constexpr complex(const _Deduction_type&) = delete;
constexpr complex(const _Deduction_type&, const _Deduction_type&) = delete;

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've been there. C++14 still needs to be supported here.


template <class _Other>
constexpr complex(const complex<_Other>&) = delete;
};
#else // ^^^ !_HAS_NONFLOATING_COMPLEX / _HAS_NONFLOATING_COMPLEX vvv
_EXPORT_STD template <class _Ty>
class complex : public _Complex_base<_Ty, _Complex_value<_Ty>> {
public:
Expand Down Expand Up @@ -1412,6 +1429,7 @@ public:
return *this;
}
};
#endif // ^^^ _HAS_NONFLOATING_COMPLEX ^^^

_EXPORT_STD template <class _Ty>
_NODISCARD _CONSTEXPR20 complex<_Ty> operator+(const complex<_Ty>& _Left, const complex<_Ty>& _Right)
Expand Down
6 changes: 6 additions & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,10 @@ _EMIT_STL_ERROR(STL1001, "Unexpected compiler version, expected MSVC Compiler 19
#error /GR implies _HAS_STATIC_RTTI.
#endif // defined(_CPPRTTI) && !_HAS_STATIC_RTTI

#ifndef _HAS_NONFLOATING_COMPLEX
#define _HAS_NONFLOATING_COMPLEX 0
#endif // !defined(_HAS_NONFLOATING_COMPLEX)

// N4950 [dcl.constexpr]/1: "A function or static data member declared with the
// constexpr or consteval specifier is implicitly an inline function or variable"

Expand Down Expand Up @@ -1398,6 +1402,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect
#define _CXX20_REMOVE_CISO646
#endif // ^^^ warning disabled ^^^

#if _HAS_NONFLOATING_COMPLEX
#if !defined(_SILENCE_NONFLOATING_COMPLEX_DEPRECATION_WARNING)
#define _DEPRECATE_NONFLOATING_COMPLEX \
[[deprecated("warning STL4037: " \
Expand All @@ -1408,6 +1413,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect
#else // ^^^ warning enabled / warning disabled vvv
#define _DEPRECATE_NONFLOATING_COMPLEX
#endif // ^^^ warning disabled ^^^
#endif // ^^^ _HAS_NONFLOATING_COMPLEX ^^^

// STL4038 is used to warn that "The contents of <meow> are available only with C++NN or later."

Expand Down
2 changes: 1 addition & 1 deletion tests/libcxx/usual_matrix.lst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

RUNALL_INCLUDE ..\universal_prefix.lst
RUNALL_CROSSLIST
* PM_CL="/EHsc /MTd /std:c++latest /permissive- /utf-8 /FImsvc_stdlib_force_include.h /wd4643"
* PM_CL="/EHsc /MTd /std:c++latest /permissive- /utf-8 /FImsvc_stdlib_force_include.h /wd4643 /D_HAS_NONFLOATING_COMPLEX=1"
Copy link

Copilot AI Apr 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test matrix change forces _HAS_NONFLOATING_COMPLEX=1 for the default libc++-compat run, which means the libc++ test job will no longer exercise the new default behavior (_HAS_NONFLOATING_COMPLEX defaults to 0 in yvals_core.h). If the goal is to validate the removal path, consider keeping the default run on the default setting and adding a separate opt-in matrix entry for _HAS_NONFLOATING_COMPLEX=1 (or gating this define to only the specific configs/tests that still require it).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

libc++ tests do assume nonfloating complex, nothing can be done here without upstream change, which I don't think will work out.

RUNALL_CROSSLIST
PM_CL="/Zc:preprocessor"
ASAN PM_CL="-fsanitize=address /Zi" PM_LINK="/debug"
Expand Down
Loading