是否可以将类型未知的变量声明为类成员变量?

时间:2018-07-29 23:17:52

标签: c++ templates mersenne-twister

所以我对mersenne_twister引擎及其功能感兴趣,因此我决定将初始化它所需的几行代码放在自己的类中,这样我只需创建该类的一个实例,然后可以得到我想要的任意范围内的任何随机数,而不必每次都需要重复这些行。

到目前为止,我已经取得了成功,但是因为我希望我的代码尽可能地可移植和高效,所以我希望根据当前的体系结构使用64位引擎。 我想避免使用由编译器定义的预处理器宏的方法,因为这对我来说似乎不是最干净的方法,并且每次我在代码中提及引擎时,都需要我使用这些宏。

我对架构l的宏看起来像这样:

#define CPU_ARCH sizeof(nullptr)*8

然后在类的私有空间中声明引擎,以便可以在构造函数中将其初始化,如下所示:

engine = mt19937(seed);

并在我的随机函数中使用它,如下所示:

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

现在看起来还不错,但是我还没有找到一种方法来实现两种具有相同名称“ engine”的体系结构,即在启动时选择要使用的引擎。

我尝试了以下操作:

  • 使用模板创建一个名为engine的变量,该变量稍后会被获取
    分配了mt19337或mt19337_64,这会导致编译器
    抱怨

    错误:数据成员'engine'不能是成员模板

具有以下实现方式:

class Random {
      public:
      [...]

      private:
      template<typename T>
      T engine;

      [...]
};
  • 使用boost :: variant,这需要我告诉
    我的GiveRnd()函数使用引擎时要使用的类型 因为类型在编译时未知,所以不可能
  • 尽管根本没有在头文件中声明引擎 导致GiveRnd()函数无法使用引擎 因为它不在同一范围内。
  • 在头文件中使用预处理器宏,然后在
    中使用typeid 查找未使用哪个引擎的源代码 可能是这样的:

    if(CPU_ARCH == 32){engine = mt19337(seed)}

    因为编译器不知道引擎将永远是
    在这种情况下为32位,并且抱怨我不能使用'='运算符 两种不同的类型。

有人对如何以至少一种干净的方式使之成为可能有想法吗?还是我需要依靠预处理器宏?

1 个答案:

答案 0 :(得分:0)

您可以通过创建一个以CPU_BITS作为模板参数并且专门用于期望值的类模板来实现依赖于CPU_BITS的行为。例如:

#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);
}