-
Notifications
You must be signed in to change notification settings - Fork 103
Description
Here's an example that won't build for pcg_t = ::pcg64 but works for pcg_t = ::pcg32.
#include <random>
#include <sstream>
#include "third_party/pcg_random/include/pcg_random.hpp"
namespace {
using pcg_t = ::pcg64;
}
int main()
{
pcg_t rng(std::random_device{}());
std::stringstream out;
out << rng;
return 0;
}
I can verify similar issues in pcg-test.cpp if you add prints to std::cout or reads from std::cin.
What I believe is happening is: you're relying on Koenig lookup to find the definitions of operator<< and operator>> in namespace pcg_extras. But pcg128_t is typically a typedef for __uint128_t; Koenig lookup doesn't work on typedefs (or more precisely, looks at the resolved type's namespace, not the typedef's.)
As I see it there are three possible fixes:
-
Move the operator definitions to the global namespace -- this is a bad idea, for one thing because anyone could have a conflicting definition.
-
Add a wrapper class around the typedef. This would solve the namespacing issue neatly; I don't know if we'd incur runtime cost from the compiler choking on the wrapper. Hopefully not but hard to prove.
-
Replace the
operator<<forpcg128_twith similar free functions named (say)InputandOutputand use SFINAE in the definitions of the engineoperator<<to prefer those if available. A bit clunky, but would work. (Also sort of necessary for theuint8_tstuff, I think.)
I'm hacking together 3) to see how bad it looks, but not done yet.