如何从成员初始化列表中调用随机生成器的 seed_seq 构造函数?
How to call the seed_seq constructor of a random generator from a member initialization list?
我有一个 class 和一个 std::mersenne_twister_engine
成员,我想用从字符串构造的 std::seed_seq
初始化它。最初我试过这个:
class A
{
private:
std::mt19937_64 rng;
public:
A(std::string seed) : rng(std::seed_seq(seed.begin(), seed.end())) { }
};
但这不能编译,因为:
(...) cannot convert argument 1 from 'std::seed_seq' to '_Seed_seq &'
我可以让它像这样工作:
class B
{
private:
std::mt19937_64 rng;
public:
B(std::string seed) {
std::seed_seq seedSeq(seed.begin(), seed.end());
rng = std::mt19937_64(seedSeq);
}
};
但是如果我理解正确的话,成员变量rng
现在会被构造两次,所以如果可能的话,我想避免这种情况。 所以,我的主要问题是: 是否可以在不初始化 rng
两次的情况下完成这项工作?
在有人建议之前,我也尝试过使用单独的成员函数来构造 std::seed_seq
对象,但是我可以编译它的唯一方法是返回一个 const ref,如下所示:
class C
{
private:
std::mt19937_64 rng;
const std::seed_seq& makeSeedSeq(std::string seed)
{
return std::seed_seq(seed.begin(), seed.end());
}
public:
C(std::string seed) : rng(makeSeedSeq(seed)) { }
};
Class C
确实可以编译,但是当使用不同的字符串进行测试时,结果总是相同的,并且总是好像种子是一个空字符串一样。我猜这是因为 makeSeedSeq
returns 对本地的引用并且结果是未定义的行为? 这是题外话,但如果有人能解释这一点以及为什么 std::seed_seq
是这样实现的,我将不胜感激。
只需将std::seed_seq
变量添加到std::mt19937_64
之前的class(变量初始化顺序很重要):
class A
{
private:
std::seed_seq seed_seq;
std::mt19937_64 rng;
public:
A(std::string const& seed)
: seed_seq(seed.begin(), seed.end())
, rng(seed_seq)
{}
std::uint32_t uniform()
{
return std::uniform_int_distribution<std::uint32_t>()(rng);
}
};
此外,我建议在构造函数中使用 const&
以避免执行 std::string
复制构造函数。
我有一个 class 和一个 std::mersenne_twister_engine
成员,我想用从字符串构造的 std::seed_seq
初始化它。最初我试过这个:
class A
{
private:
std::mt19937_64 rng;
public:
A(std::string seed) : rng(std::seed_seq(seed.begin(), seed.end())) { }
};
但这不能编译,因为:
(...) cannot convert argument 1 from 'std::seed_seq' to '_Seed_seq &'
我可以让它像这样工作:
class B
{
private:
std::mt19937_64 rng;
public:
B(std::string seed) {
std::seed_seq seedSeq(seed.begin(), seed.end());
rng = std::mt19937_64(seedSeq);
}
};
但是如果我理解正确的话,成员变量rng
现在会被构造两次,所以如果可能的话,我想避免这种情况。 所以,我的主要问题是: 是否可以在不初始化 rng
两次的情况下完成这项工作?
在有人建议之前,我也尝试过使用单独的成员函数来构造 std::seed_seq
对象,但是我可以编译它的唯一方法是返回一个 const ref,如下所示:
class C
{
private:
std::mt19937_64 rng;
const std::seed_seq& makeSeedSeq(std::string seed)
{
return std::seed_seq(seed.begin(), seed.end());
}
public:
C(std::string seed) : rng(makeSeedSeq(seed)) { }
};
Class C
确实可以编译,但是当使用不同的字符串进行测试时,结果总是相同的,并且总是好像种子是一个空字符串一样。我猜这是因为 makeSeedSeq
returns 对本地的引用并且结果是未定义的行为? 这是题外话,但如果有人能解释这一点以及为什么 std::seed_seq
是这样实现的,我将不胜感激。
只需将std::seed_seq
变量添加到std::mt19937_64
之前的class(变量初始化顺序很重要):
class A
{
private:
std::seed_seq seed_seq;
std::mt19937_64 rng;
public:
A(std::string const& seed)
: seed_seq(seed.begin(), seed.end())
, rng(seed_seq)
{}
std::uint32_t uniform()
{
return std::uniform_int_distribution<std::uint32_t>()(rng);
}
};
此外,我建议在构造函数中使用 const&
以避免执行 std::string
复制构造函数。