我想将随机引擎分配给变量。
基本原因:我希望能够在测试和生产代码之间切换随机引擎。测试应使用比生产代码更可预测的随机生成器。
使用下面的示例代码可行,但我必须将<T>
拖到我不想要的所有代码中。
#include <random>
#include <iostream>
class MyEngine {
public:
typedef int result_type;
result_type operator()() {
return 42;
}
constexpr result_type min() {
return 0;
}
constexpr result_type max() {
return 100;
}
};
template <class T>
struct EngineHolder {
T engine;
EngineHolder(const T& engine) : engine(engine) { }
};
//template <class T>
void doSomeWork(EngineHolder/*<T>*/* engineHolder) {
std::uniform_int_distribution<int> distribution(30, 50);
for (int i = 0; i < 50; i++) {
int v = distribution(engineHolder->engine);
std::cout << v << " ";
}
std::cout << std::endl;
}
int main() {
// Engine 1
std::default_random_engine engine1;
EngineHolder<std::default_random_engine> foo1(engine1);
doSomeWork(&foo1);
// Engine 2
std::default_random_engine engine2(145457);
EngineHolder<std::default_random_engine> foo2(engine2);
doSomeWork(&foo2);
// Engine 3
std::linear_congruential_engine<unsigned int, 1, 1, 10> engine3;
EngineHolder<std::linear_congruential_engine<unsigned int, 1, 1, 10>> foo3(engine3);
doSomeWork(&foo3);
// My Engine
MyEngine myEngine;
EngineHolder<MyEngine> foo4(myEngine);
doSomeWork(&foo4);
return 0;
}
我想通过定义一个要使用哪个引擎的宏来让预处理器完成这个任务 现在我想知道还有另一种方式吗?
答案 0 :(得分:2)
看起来你想要一种方法将任何类型的随机数生成器传递给Collectors.counting()
。如果是这种情况,我只需将函数模板化为
doSomeWork
然后你可以像
一样使用它template <class Engine>
void doSomeWork(Engine engine) {
std::uniform_int_distribution<int> distribution(30, 50);
for (int i = 0; i < 50; i++) {
int v = distribution(engine);
std::cout << v << " ";
}
std::cout << std::endl;
}
现在您根本不需要指定模板类型。
答案 1 :(得分:2)
对uniform_int_distribution::operator()
的调用对参数的要求很少,详细信息为UniformRandomNumberGenerator。它必须提供成员result_type
,min()
,max()
和operator()()
。您已经使用模板类完成了这项工作。
您可以创建包含这些方法的接口,并将该接口传递到doSomeWork
而无需模板。具体的EngineHolder
类将从接口派生。唯一的限制是您不能创建typedef
虚拟,因此所有派生类必须使用相同的result_type
。
class EngineHolderInterface {
public:
typedef int result_type;
virtual ~EngineHolderInterface() {};
virtual result_type operator()() = 0;
virtual result_type min() = 0;
virtual result_type max() = 0;
};
template <class T>
struct EngineHolder : public EngineHolderInterface {
T engine;
EngineHolder(const T& engine) : engine(engine) { }
virtual result_type operator()() { return engine(); }
virtual result_type min() { return engine.min(); }
virtual result_type max() { return engine.max(); }
};
void doSomeWork(EngineHolderInterface* engineHolder) {
std::uniform_int_distribution<int> distribution(30, 50);
for (int i = 0; i < 50; i++) {
int v = distribution(*engineHolder);
std::cout << v << " ";
}
std::cout << std::endl;
}