为 STL 随机数生成器编写工厂方法
Writing a Factory method for STL random number generators
我正在尝试通过配置文件提供一个接口,供我的用户为他们正在使用的某些参数选择发行版。为此,我想使用 STL 随机数生成器算法。
假设我的程序从命令行读取 JSON。对于下面提供的 JSON,程序需要意识到它应该从具有给定平均值和标准变异的正态分布中生成一个随机数。(我使用与 STL 库相同的参数名称进行清除。
{
"dist": "normal_distribution",
"mean": 0.1,
"stddev": 0.5
}
到目前为止,我可以轻松解析 JSON,并使用每个发行版的param_type
来初始化发行版。我使用名称来决定哪个分布来决定param_type
和分布。
我不知道的是如何很好地实现这一点。我知道我应该为此提供某种工厂方法,传递 JSON,并吐出一个函数或类。如果我想返回一个类的实例,比如说生成器的unique_ptr
,我需要定义一个抽象类,例如,RandDist
并编写某种适配器来合并我的输入,....我一般不需要上课很多东西,只要gen()
的方法就足够了。
我想知道是否有人对此有想法。或者,如果有人知道可以做到这一点的库。
附言输入不必是JSON对象,任何哈希表本身都可以工作。
您描述了一种非常标准的方式来处理这种情况 - 只有一个虚拟方法的抽象RandomGenerator
类gen()
。
然后,它将具有NormalDistributionGenerator
,UniformDistributionGenerator
等实现,构造函数接受适当的分布参数集并将STL内容初始化为成员。 这些具体的类将仅在生成器创建例程中直接使用,并在其他地方用作抽象RandomGenerator
。
所以创建例程将看起来像这样
std::unique_ptr<RandomGenerator> CreateRandomGenerator(const Info& info) {
switch (info.type) {
case Type::Normal:
return std::make_unique<NormalDistributionGenerator>(info.mean(), info.stddev());
case Type::Uniform:
return std::make_unique<UniformDistributionGenerator>(info.a(), info.b());
// ...
}
}
Info
- 是一个保存分布信息的类(一些 JSON 包装器,映射/hash_table - 任何最适合您的情况)。
因此,您肯定需要编写一些样板代码来使其工作,但它会使RandomGenerator
的使用变得简单明了,并且添加新类型的发行版将非常简单,并且只需要在单个地方修改代码 - 工厂方法。
我试图将样板保持在最低限度。假设:
-
您提前知道发电机的类型(如果您需要发电机也是动态的,则可以轻松切换)
-
所有发行版都生成
double
s(这几乎是烘焙的,因为 API 必须返回一些具体的东西才能体面地使用) -
所有分布都可以从
double
参数构造(也可以使用代理对象进行调整,但根据您的实际 JSON 库,工作可能已经在那里完成) -
我已经使用 GCC 预处理器扩展来处理零参数情况,但宏当然可以重写为不需要它。
using Generator = std::mt19937;
using Distribution = std::function<double(Generator &)>;
using Json = std::map<std::string, std::string>;
template <class DistributionType, class... Parameters>
Distribution make_distribution_impl(Json const &json, Parameters... parameters) {
return DistributionType{std::stod(json.at(parameters))...};
}
Distribution make_distribution(Json const &json) {
auto const &distributionName = json.at("dist");
#define generate_distribution_factory(name_, ...)
if(distributionName == #name_)
return make_distribution_impl<std::name_<double>>(json, ## __VA_ARGS__)
generate_distribution_factory(uniform_real_distribution, "a", "b");
generate_distribution_factory(normal_distribution, "mean", "stddev");
// ...
#undef generate_distribution_factory
throw std::runtime_error{"Unknown distribution " + distributionName};
}
在Wandbox上观看直播
- 如何在工厂方法中返回指向基于基础操作系统的派生类的有效指针
- 工厂方法:分配和strcpy_s的差异
- 在基类中编写工厂方法
- 从工厂方法返回的ComPtr的引用计数增加两次
- 工厂方法模式使用继承而抽象工厂模式使用组合如何
- 在C++中将返回unique_ptr和shared_ptr的两个工厂方法组合为一个
- 工厂方法中的访问冲突
- 如何模板静态工厂方法?
- 工厂方法创建的对象应该在哪里删除?
- 如何禁用在工厂方法之外创建/复制 obj?
- 为 STL 随机数生成器编写工厂方法
- 此工厂方法是否会导致争用条件?
- 如何从JSON String创建工厂方法
- C++可扩展的工厂方法
- 总结工厂方法
- 对不同的参数使用工厂方法模式
- 使用工厂方法时编译器错误:无法转换"const std::p air<char* const
- Boost::log 使用静态工厂方法
- 如何使用工厂方法创建不同的对象
- 我可以有一个仅使用工厂方法创建的成员变量吗?