diff --git a/include/pcg_extras.hpp b/include/pcg_extras.hpp index 70dbf5c..a49b1a3 100644 --- a/include/pcg_extras.hpp +++ b/include/pcg_extras.hpp @@ -115,11 +115,21 @@ namespace pcg_extras { * * This code provides enough functionality to print 128-bit ints in decimal * and zero-padded in hex. It's not a full-featured implementation. + * + * Note that we cannot simply define operator<< implementations, + * because pcg128_t is (sometimes!) a typedef; Koenig lookup on typedefs + * looks at the resolved type, which is __uint128_t in the global namespace. */ +template +std::basic_ostream& +Output(std::basic_ostream& out, const T &t) { + return out << t; +} + template std::basic_ostream& -operator<<(std::basic_ostream& out, pcg128_t value) +Output(std::basic_ostream& out, pcg128_t value) { auto desired_base = out.flags() & out.basefield; bool want_hex = desired_base == out.hex; @@ -161,9 +171,15 @@ operator<<(std::basic_ostream& out, pcg128_t value) return out << pos; } +template +std::basic_istream& +Input(std::basic_istream& in, T &t) { + return in >> t; +} + template std::basic_istream& -operator>>(std::basic_istream& in, pcg128_t& value) +Input(std::basic_istream& in, pcg128_t& value) { typename std::basic_istream::sentry s(in); diff --git a/include/pcg_random.hpp b/include/pcg_random.hpp index ca197da..cb5d641 100644 --- a/include/pcg_random.hpp +++ b/include/pcg_random.hpp @@ -561,16 +561,18 @@ operator<<(std::basic_ostream& out, auto space = out.widen(' '); auto orig_fill = out.fill(); - out << rng.multiplier() << space - << rng.increment() << space - << rng.state_; + pcg_extras::Output(out, rng.multiplier()); + out << space; + pcg_extras::Output(out, rng.increment()); + out << space; + pcg_extras::Output(out, rng.state_); + out << space; out.flags(orig_flags); out.fill(orig_fill); return out; } - template >(std::basic_istream& in, auto orig_flags = in.flags(std::ios_base::dec | std::ios_base::skipws); itype multiplier, increment, state; - in >> multiplier >> increment >> state; - + pcg_extras::Input(in, multiplier); + pcg_extras::Input(in, increment); + pcg_extras::Input(in, state); if (!in.fail()) { bool good = true; if (multiplier != rng.multiplier()) { diff --git a/test-high/pcg-test.cpp b/test-high/pcg-test.cpp index 1c5c09e..a6c942e 100644 --- a/test-high/pcg-test.cpp +++ b/test-high/pcg-test.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -139,8 +140,9 @@ int main(int argc, char** argv) printf(" Rolls:"); for (int i = 0; i < 33; ++i) cout << " " << (uint32_t(rng(6)) + 1); - cout << "\n --> rolling dice used " - << (rng - rng_copy) << " random numbers" << endl; + cout << "\n --> rolling dice used " + << static_cast(rng - rng_copy) + << " random numbers" << endl; /* Deal some cards using pcg_extras::shuffle, which follows * the algorithm for shuffling that most programmers would expect. @@ -167,6 +169,13 @@ int main(int argc, char** argv) cout << "\n" << endl; } + // Ensure that the input/output functions work. + std::stringstream ss; + ss << rng; + RNG from_string; + ss >> from_string; + assert(from_string == rng); + return 0; }