std::complex
over-encapsulatedSection: 29.4 [complex.numbers] Status: CD1 Submitter: Gabriel Dos Reis Opened: 2002-11-08 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [complex.numbers].
View all issues with CD1 status.
Discussion:
The absence of explicit description of std::complex<T>
layout
makes it imposible to reuse existing software developed in traditional
languages like Fortran or C with unambigous and commonly accepted
layout assumptions. There ought to be a way for practitioners to
predict with confidence the layout of std::complex<T>
whenever T
is a numerical datatype. The absence of ways to access individual
parts of a std::complex<T>
object as lvalues unduly promotes
severe pessimizations. For example, the only way to change,
independently, the real and imaginary parts is to write something like
complex<T> z; // ... // set the real part to r z = complex<T>(r, z.imag()); // ... // set the imaginary part to i z = complex<T>(z.real(), i);
At this point, it seems appropriate to recall that a complex number
is, in effect, just a pair of numbers with no particular invariant to
maintain. Existing practice in numerical computations has it that a
complex number datatype is usually represented by Cartesian
coordinates. Therefore the over-encapsulation put in the specification
of std::complex<>
is not justified.
Proposed resolution:
Add the following requirements to 29.4 [complex.numbers] as 26.3/4:
If
z
is an lvalue expression of type cvstd::complex<T>
then
- the expression
reinterpret_cast<cv T(&)[2]>(z)
is well-formed; andreinterpret_cast<cv T(&)[2]>(z)[0]
designates the real part ofz
; andreinterpret_cast<cv T(&)[2]>(z)[1]
designates the imaginary part ofz
.Moreover, if
a
is an expression of pointer type cvcomplex<T>*
and the expressiona[i]
is well-defined for an integer expressioni
then:
reinterpret_cast<cv T*>(a)[2*i]
designates the real part ofa[i]
; andreinterpret_cast<cv T*>(a)[2*i+1]
designates the imaginary part ofa[i]
.
In 29.4.3 [complex] and [complex.special] add the following member functions
(changing T
to concrete types as appropriate for the specializations).
void real(T); void imag(T);
Add to 29.4.4 [complex.members]
T real() const;Returns: the value of the real component
void real(T val);Assigns
val
to the real component.T imag() const;Returns: the value of the imaginary component
void imag(T val);Assigns
val
to the imaginary component.
[Kona: The layout guarantee is absolutely necessary for C
compatibility. However, there was disagreement about the other part
of this proposal: retrieving elements of the complex number as
lvalues. An alternative: continue to have real()
and imag()
return
rvalues, but add set_real()
and set_imag()
. Straw poll: return
lvalues - 2, add setter functions - 5. Related issue: do we want
reinterpret_cast as the interface for converting a complex to an
array of two reals, or do we want to provide a more explicit way of
doing it? Howard will try to resolve this issue for the next
meeting.]
[pre-Sydney: Howard summarized the options in n1589.]
[ Bellevue: ]
Second half of proposed wording replaced and moved to Ready.
[ Pre-Sophia Antipolis, Howard adds: ]
Added the members to [complex.special] and changed from Ready to Review.
[ Post-Sophia Antipolis: ]
Moved from WP back to Ready so that the "and [complex.special]" in the proposed resolution can be officially applied.
Rationale:
The LWG believes that C99 compatibility would be enough justification for this change even without other considerations. All existing implementations already have the layout proposed here.