Re: Defect report [N2134]: Missing IO roundtrip for random number engines
The IO operators for random number objects are allowed to alter the
characteristics of the stream as needed during the input or output of the=
object, and restore the stream state after the IO. The base implementatio=
n
for the new random libraries does just that.
"Daniel Kr=FCgler" <daniel.kruegler@googlemail.com> wrote in message
news:1173313685.446786.44770@n33g2000cwc.googlegroups.com...
Table 98 and para 5 in [rand.req.eng]-26.4.1.3 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.
Proposed resolution:
1) In table 98 from 26.4.1.3 in column "pre/post-condition",
row expression "is >> x" change
"Sets v's state as determined by
reading its textual representation
from is.[..]"
to
"Sets v's state as determined by
reading its textual representation
with is.fmtflags set to ios_base::dec
from is.[..]"
2) In table 98 from 26.4.1.3 in column "pre/post-condition",
row expression "os << x" change
"With os.fmtflags set to
ios_base::dec|ios_base::
fixed|ios_base::left and[..]"
to
"With os.fmtflags set to
ios_base::dec|ios_base::
left and[..]"
Greetings from Bremen,
Daniel Kr=FCgler
---
[ comp.std.c++ is moderated. To submit articles, try just posting with=
]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu =
]
[ --- Please see the FAQ before posting. --- =
]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html =
]
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]