c++templatesmersenne-twister

Is it possible to declare a variable of unknown type as a class member variable?


So I've been interested by the mersenne_twister engine and what it can do, so I decided to put the few lines of code required to initialize it inside my own class so that i simply have to create an instance of that class and can get any random numbers in any range i want without having to repeat those lines every time I need it.

I have suceeded so far but because I want my code to be as portble and efficient as possible I want to use the 64-bit engine depending on the architecture present. I would like to avoid the way of using preprocessor macros defined by the compiler as that doesn't seem like the cleanest approach to me and would also require me to use the macros every time i mention the engine in my code.

My macro for the architecture l looks like this:

#define CPU_ARCH sizeof(nullptr)*8

And I declare the engine in the private space of the class so that i can init it in the constructor like this:

engine = mt19937(seed);

and use it in my random function like this:

double Random::giveRnd() {
    return distribution(engine);
}

This looks fine right now but I have yet to find a way to implement both architectures with the same name "engine" in a way that the engine to be used is chosen at startup.

I have attempted the following:

with the following implementation:

class Random {
      public:
      [...]

      private:
      template<typename T>
      T engine;

      [...]
};

Does anyone have an idea on how to make this possible in a atleast somewhat clean way? Or do I need to fall back on the preprocessor macros?


Solution

  • You can implement behaviour that depends on CPU_BITS by making a class template that takes CPU_BITS as a template argument, and is specialized for expected values. For example:

    #include <random>
    
    template<size_t N> struct CpuOpts;
    template<> struct CpuOpts<32> { using EngineType = std::mt19937; };
    template<> struct CpuOpts<64> { using EngineType = std::mt19937_64; };
    
    enum { CPU_BITS = sizeof(nullptr)*8 };
    using CurrentCpuOpts = CpuOpts<CPU_BITS>;
    
    struct Random
    {
        CurrentCpuOpts::EngineType engine;
    };
    
    int main()
    {
        Random r;
        r.engine.seed(123456);
    }