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.

### 654. Missing IO roundtrip for random number engines

Section: 28.5.3.4 [rand.req.eng] Status: CD1 Submitter: Daniel Krügler Opened: 2007-03-08 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [rand.req.eng].

View all issues with CD1 status.

Discussion:

Table 98 and para 5 in 28.5.3.4 [rand.req.eng] specify the IO insertion and extraction semantic of random number engines. It can be shown, v.i., that the specification of the extractor cannot guarantee to fulfill the requirement from para 5:

> If a textual representation written via os << x was subsequently read via is >> v, then x == v provided that there have been no intervening invocations of x or of v.

The problem is, that the extraction process described in table 98 misses to specify that it will initially set the if.fmtflags to ios_base::dec, see table 104:

> dec: converts integer input or generates integer output in decimal base

Proof: The following small program demonstrates the violation of requirements (exception safety not fulfilled):

>     #include <cassert>
>     #include <ostream>
>     #include <iostream>
>     #include <iomanip>
>     #include <sstream>

>     class RanNumEngine {
>       int state;
>     public:
>       RanNumEngine() : state(42) {}

>       bool operator==(RanNumEngine other) const {
>           return state == other.state;
>       }

>       template <typename Ch, typename Tr>
>       friend std::basic_ostream<Ch, Tr>& operator<<(std::basic_ostream<Ch, Tr>& os, RanNumEngine engine) {
>         Ch old = os.fill(os.widen(' ')); // Sets space character
>         std::ios_base::fmtflags f = os.flags();
>         os << std::dec << std::left << engine.state; // Adds ios_base::dec|ios_base::left
>         os.fill(old); // Undo
>         os.flags(f);
>         return os;
>       }

>       template <typename Ch, typename Tr>
>       friend std::basic_istream<Ch, Tr>& operator>>(std::basic_istream<Ch, Tr>& is, RanNumEngine& engine) {
>            // Uncomment only for the fix.

>         //std::ios_base::fmtflags f = is.flags();
>         //is >> std::dec;
>         is >> engine.state;
>         //is.flags(f);
>         return is;
>       }
>     };

>     int main() {
>         std::stringstream s;
>         s << std::setfill('#'); // No problem
>             s << std::oct; // Yikes!
>             // Here starts para 5 requirements:
>         RanNumEngine x;
>         s << x;
>         RanNumEngine v;
>         s >> v;
>         assert(x == v); // Fails: 42 == 34
>     }

A second, minor issue seems to be, that the insertion description from table 98 unnecessarily requires the addition of ios_base::fixed (which only influences floating-point numbers). Its not entirely clear to me whether the proposed standard does require that the state of random number engines is stored in integral types or not, but I have the impression that this is the indent, see e.g. p. 3

> The specification of each random number engine defines the size of its state in multiples of the size of its result_type.

If other types than integrals are supported, then I wonder why no requirements are specified for the precision of the stream.

See N2391 and N2423 for some further discussion.

Proposed resolution:

Adopt the proposed resolution in N2423.

[ Kona (2007): The LWG adopted the proposed resolution of N2423 for this issue. The LWG voted to accelerate this issue to Ready status to be voted into the WP at Kona. ]