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

### 2714. `complex` stream extraction underspecified

Section: 28.4.6 [complex.ops] Status: New Submitter: Tim Song Opened: 2016-05-23 Last modified: 2018-10-16

Priority: 3

View all other issues in [complex.ops].

View all issues with New status.

Discussion:

The specification of `operator>>(istream&, complex<T>&)` is extremely short on details. It currently reads, in its entirety (28.4.6 [complex.ops]/12-15):

>     template<class T, class charT, class traits>
>     basic_istream<charT, traits>& operator>>(basic_istream<charT, traits>& is, complex<T>& x);

> > Effects: Extracts a complex number `x` of the form: `u`, `(u)`, or `(u,v)`, where `u` is the real part and `v` is the imaginary part (31.7.5.3 [istream.formatted]).

> > Requires: The input values shall be convertible to `T`.

> > If bad input is encountered, calls `is.setstate(ios_base::failbit)` (which may throw `ios::failure` (31.5.4.4 [iostate.flags])).

> > Returns: `is`.

> > Remarks: This extraction is performed as a series of simpler extractions. Therefore, the skipping of whitespace is specified to be the same for each of the simpler extractions.

It is completely unclear:

- which "simpler extractions" are performed,
- how the extracted characters are matched to the special characters `'('`, `')'` and `','` (by `==`, or by `traits::eq`),
- what is left in the stream on failure. (For example, with `"(0, 0]"`, libstdc++ extracts the `]` while libc++ leaves it in the stream.)

Previous resolution [SUPERSEDED]:

> > Drafting note: the following wording is based on:
> > - Characters are extracted using `operator>>` and compared using `traits::eq`.
> > - Mismatched characters are returned to the stream.

> This wording is relative to N4582.

> 1. Replace 28.4.6 [complex.ops]/12-15 with the following paragraphs:

>    >     template<class T, class charT, class traits>
>    >     basic_istream<charT, traits>&
>    >     operator>>(basic_istream<charT, traits>& is, complex<T>& x);

>    > > -?- Effects: First, extracts a character from `is`.

>    > > - If the character extracted is equal to `is.widen('(')`, extracts an object `u` of type `T` from `is`, then extracts a character from `is`.
>    > >   - If this character is equal to `is.widen(')')`, then assigns `complex<T>(u)` to `x`.
>    > >   - Otherwise, if this character is equal to `is.widen(',')`, extracts an object `v` of type `T` from `is`, then extracts a character from `is`. If this character is equal to `is.widen(')')`, then assigns `complex<T>(u, v)` to `x`; otherwise returns the character to `is` and the extraction fails.
>    > >   - Otherwise, returns the character to `is` and the extraction fails.
>    > > - Otherwise, returns the character to `is`, extracts an object `u` of type `T` from `is`, and assigns `complex<T>(u)` to `x`.
>    > > In the description above, characters are extracted from `is` as if by `operator>>` (31.7.5.3.3 [istream.extractors]), and returned to the stream as if by `basic_istream::putback` (31.7.5.4 [istream.unformatted]). Character equality is determined using `traits::eq`. An object `t` of type `T` is extracted from `is` as if by `is >> t`.

>    > > If any extraction operation fails, no further operation is performed and the whole extraction fails.

>    > > On failure, calls `is.setstate(ios_base::failbit)` (which may throw `ios::failure` (31.5.4.4 [iostate.flags])).

>    > > -?- Returns: `is`.

>    > > -?- [Note: This extraction is performed as a series of simpler extractions. Therefore, the skipping of whitespace is specified to be the same for each of the simpler extractions. — end note]

[2017-12-13 Tim Song adjusts the P/R to avoid relying on `putback`.]

Proposed resolution:

> Drafting note: the following wording assumes that:
> - Characters are extracted using `operator>>` and compared using `traits::eq`.
> - Mismatched characters are not extracted.
> - `x` is assigned a value-initialized `complex` on failure for consistency with the arithmetic extractors (compare LWG 696).

This wording is relative to N4778.

1. Replace 28.4.6 [complex.ops]/12-16 with the following paragraphs:

   >     template<class T, class charT, class traits>
   >     basic_istream<charT, traits>&
   >     operator>>(basic_istream<charT, traits>& is, complex<T>& x);

   > > -?- Effects: Let `PEEK(is)` be a formatted input function (31.7.5.3.1 [istream.formatted.reqmts]) of `is` that returns the next character that would be extracted from `is` by `operator>>`. [Note: The `sentry` object is constructed and destroyed, but the returned character is not extracted from the stream. — end note]

   > > - If `PEEK(is)` is not equal to `is.widen('(')`, extracts an object `u` of type `T` from `is`, and assigns `complex<T>(u)` to `x`.
   > > - Otherwise, extracts that character from `is`, then extracts an object `u` of type `T` from `is`, then:
   > >   - If `PEEK(is)` is equal to `is.widen(')')`, then extracts that character from `is` and assigns `complex<T>(u)` to `x`.
   > >   - Otherwise, if it is equal to `is.widen(',')`, then extracts that character from `is` and then extracts an object `v` of type `T` from `is`, then:
   > >     - If `PEEK(is)` is equal to `is.widen(')')`, then extracts that character from `is` and assigns `complex<T>(u, v)` to `x`.
   > >     - Otherwise, the extraction fails.
   > >   - Otherwise, the extraction fails.
   > > In the description above, characters are extracted from `is` as if by `operator>>` (31.7.5.3.3 [istream.extractors]), character equality is determined using `traits::eq`, and an object `t` of type `T` is extracted from `is` as if by `is >> t`.

   > > If any extraction operation fails, no further operation is performed and the whole extraction fails.

   > > On failure, assigns `complex<T>()` to `x` and calls `is.setstate(ios_base::failbit)` (which may throw `ios::failure` (31.5.4.4 [iostate.flags])).

   > > -?- Returns: `is`.

   > > -?- [Note: This extraction is performed as a series of simpler extractions. Therefore, the skipping of whitespace is specified to be the same for each of the simpler extractions. — end note]