3

I have a C++17 question about std::complex<float>, std::complex<double>, and std::complex<long double> and their member functions real() and imag().

Obviously, these member functions cannot throw an exception as they just return a value by copy of built-in floating-point type.

So why are they not specified noexcept?

peer
  • 4,171
  • 8
  • 42
  • 73
x y
  • 557
  • 3
  • 10
  • For polymorphism with any other specializations anyone may choose to create? – slim Aug 23 '19 at 09:36
  • 1
    No, that's not it: "The effect of instantiating the template complex for any type other than float, double, or long double is unspecified." – Marshall Clow Aug 23 '19 at 14:34

1 Answers1

1

A similar question has been asked here but the context is slightly different. The way noexcept is generally specified by the standard library is to do so only when it would be potentially beneficial. Keep in mind that a function lacking noexpect specification may still be called from within a noexcept function (unlike the analogous situation for const), so omitting noexcept is not restrictive in any way. Merely, noexcept indicates to the compiler that no exception handling is necessary/possible which can convey dramatic performance benefits, especially in situations where the compiler can only reason on the function based on its signature. However std::complex::(real|imag) are both likely to be inlined anyway and the exception handling can be elided in that case anyway.

That being said, I can also not see anything wrong with declaring noexcept in this case. Generally, one should be cautious not to declare any library API noexcept as this potentially restricts implementators. In the case of std::complex, however, the wiggle room for implementations is so narrow that it is fair to stipulate that no exceptions could be thrown. My guess is that, std::complex predating noexcept, there was never enough of a reason to add noexcept specifiers retroactively.

Jonas Greitemann
  • 1,011
  • 10
  • 25
  • Thanks. Do you mean a compiler optimization like inlining might "correct" a constant expression like the `noexcept` operator? That is, although `noexcept(std::complex{}.real())` yields `false` due to the missing `noexcept` specifier, the branch for `true` might still be taken because an optimizing compiler knows better? I somehow doubt that the C++ standard relies on that concept. For example, what happens with code in a DLL that is not statically linked? No compiler can optimize in that case and the `noexcept` specifier would be the only way to enable the branch for `true`. – x y Aug 31 '19 at 08:49