I am writing a C++ wrapper class for generating uniform distributions for integer and floating-point types using the <random>
library. I created an abstract base class which the specialised classes for the two types would derive from. However, I can only access the members of the base class via the this
pointer. This is not what I expected, as I thought derived classes could directly access their base class's protected members. Can someone explain if there is a nuance I'm missing here? My code is shown below.
Note: the function GetTypeCategory()
simply categorises all integer types together and likewise for the floating-point types. It return an enumerator of type TypeCategory
.
/** Random base class. */
template <typename data_type, TypeCategory type_category = GetTypeCategory(data_type())>
class RandomBase
{
protected:
std::random_device Device; /** Random device. */
std::mt19937 Generator; /** Random number generator. */
/** Protected constructor. */
RandomBase() : Generator(Device()) {};
public:
/** Virtual destructor. */
virtual ~RandomBase() {};
/** Pure virtual random number generating method. */
virtual inline data_type Get() = 0;
};
/** Forward declaration of the specialised Random classes. */
template <typename data_type, TypeCategory type_category = GetTypeCategory(data_type())>
class Random;
/** Random integer class. */
template <typename data_type>
class Random<data_type, TypeCategory::Integer> : public RandomBase<data_type, TypeCategory::Integer>
{
private:
std::uniform_int_distribution<data_type> Distribution;
public:
Random() = delete;
Random(const data_type& _min, const data_type& _max) : RandomBase<data_type, TypeCategory::Integer>(), Distribution(_min, _max) {}
~Random() = default;
inline data_type Get() { return Distribution(this->Generator); }
// inline data_type Get() { return Distribution(Generator); } // This does not compile as Generator is not visible from Random
};
/** Random floating-point class. */
template <typename data_type>
class Random<data_type, TypeCategory::FloatingPoint> : public RandomBase<data_type, TypeCategory::FloatingPoint>
{
private:
std::uniform_real_distribution<data_type> Distribution;
public:
Random() = delete;
Random(const data_type& _min, const data_type& _max) : RandomBase<data_type, TypeCategory::FloatingPoint>(), Distribution(_min, _max) {}
~Random() = default;
inline data_type Get() { return Distribution(this->Generator); }
// inline data_type Get() { return Distribution(Generator); } // This does not compile as Generator is not visible from Random
};
/** Template argument deduction guide for the Random class. */
template <typename data_type> Random(data_type, data_type) -> Random<data_type>;