This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of CD1 status.

387. std::complex over-encapsulated

Section: 28.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.


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 28.4 [complex.numbers] as 26.3/4:

If z is an lvalue expression of type cv std::complex<T> then

Moreover, if a is an expression of pointer type cv complex<T>* and the expression a[i] is well-defined for an integer expression i then:

In 28.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 28.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.


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.