【问题标题】:Is it possible to declare a variable of unknown type as a class member variable?是否可以将未知类型的变量声明为类成员变量?
【发布时间】:2019-01-06 04:39:10
【问题描述】:

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

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

我的架构 l 宏如下所示:

#define CPU_ARCH sizeof(nullptr)*8

我在类的私有空间中声明引擎,这样我就可以在构造函数中像这样初始化它:

engine = mt19937(seed);

并像这样在我的随机函数中使用它:

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

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

我尝试了以下方法:

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

    错误:数据成员“引擎”不能是成员模板

使用以下实现:

class Random {
      public:
      [...]

      private:
      template<typename T>
      T engine;

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

    如果(CPU_ARCH==32){引擎= mt19337(种子)}

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

有没有人知道如何以一种至少有点干净的方式实现这一点?还是我需要依赖预处理器宏?

【问题讨论】:

  • " 每次我在代码中提到引擎时,我都需要使用宏。”为什么?您可以让您的代码使用这些宏来定义您可以根据需要一致引用的其他内容。或者只是有条件地声明一个 using EngineType= #else using EngineType=,对吧?
  • 请提出一个特定的编程问题(代码、目标和您需要帮助的技术障碍)并提供您迄今为止所做工作的代码minimal reproducible example。 Stack Overflow 不适用于代码审查或设计建议。
  • @M.M 你能举例说明如何实现吗?我一般对模板不太熟悉,我不知道为什么需要将其设为静态以及如何在模板中实现 CPU_ARCH。
  • @xaxxon 我不喜欢预定义的宏,因为它们因编译器而异,而且我不能在#if 语句中使用 CPU_ARCH,因为预处理器在编译之前不知道 sizeof(nullptr) 是什么文件。
  • @MM 我明白了,不,我真的不需要它,如果可能只是因为我需要它的罕见机会,那就太酷了,但如果它会使代码复杂化,那就没有必要了太多了。

标签: c++ templates mersenne-twister


【解决方案1】:

您可以通过创建一个将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);
}

【讨论】:

  • 经过一番谷歌搜索以找出其工作原理:DI 已成功将其实现到我的班级中,只进行了一次修改,删除了 Engine&lt;CPU_BITS&gt;::type engine; 周围的 struct Random 以简化它一点点或除了可读性之外,您这样做还有什么具体原因吗? engine.seed 是否也等同于 engine(seed)?除此之外,这对我的目的来说是完美的,非常感谢你为我节省了几个小时的时间:D
  • @TheSupremeGod 您的原始代码中有 Random 类。是的,调用seed 函数相当于在创建时播种。
  • 好的,所以在我盲目地将您从EngineCpuOpts 的编辑放入我的代码并上床尝试弄清楚 Opts 的含义之前,你能告诉我吗我?很抱歉成为世界上最挑剔的程序员:D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-24
  • 1970-01-01
相关资源
最近更新 更多