【发布时间】:2019-11-16 21:40:45
【问题描述】:
我使用std::uniform_int_distribution 来生成素数(p)。我将分发对象放在一个匿名命名空间中——这对于成年人来说似乎是 C++ 的“静态链接”......
namespace
{
// a more pedantic range: [2, 18446744073709551557]
std::uniform_int_distribution<uint64_t> p_dist {2};
std::mt19937 rng; // (sufficient IV states for uniqueness)
}
请注意,我在可移植代码允许的范围内尽可能彻底地播种 Mersenne Twister。不过,这对这个问题并不重要。这只是为了向读者保证我正在正确使用随机工具:
std::seed_seq::result_type data[rng.state_size];
std::random_device rdev;
std::generate_n(data, rng.state_size, std::ref(rdev));
std::seed_seq rng_seed (data, data + rng.state_size);
rng.seed(rng_seed);
这很方便,因为我有一个确定性的u64_prime(p) 函数,使用(7) bases,可以确定(p) 是否为素数:
uint64_t p;
while (!u64_prime(p = p_dist(rng)))
;
现在我创建一个std::function 对象:
std::function<uint64_t()> zp_rng = std::bind(
decltype(p_dist){0, p - 1}, std::ref(rng));
这个函数:zp_rng()可以被调用来返回Z(p)中的一个随机数。也就是说,使用分布对象为:[0, p - 1] 来自引用的 rng 的结果。
现在这非常令人印象深刻 - 但我通过剪切和粘贴有效地采用了它,而对std::function 之间的交互作用以及给std::bind 的参数的交互作用知之甚少.
decltype(p_dist){0, p - 1} 并没有让我感到困惑——这只是说明我们仍想使用std::uniform_int_distribution 的一种方式。我对std::ref(rng) 的理解是,它可以防止 rng 的本地副本被实例化,而是强制使用引用......所以:
问:有效确定:dist(rng) 被使用的基本规则是什么 - 我不明白为什么 std::bind 会强制执行这种交互。很多交互似乎都基于 operator () 方法。
Q:std::function 在cppreference.com 上被称为“通用多态函数包装器”。那么是不是封装了一个uint64_t返回类型的函数呢?或者再次使用operator () 语法来驱动函数的概念?
尽管这些结构非常有用,但我觉得我在这里某种程度上是货物狂热的编程。我正在寻找一个能以具体方式解决任何歧义并为类似问题增加洞察力的答案 - bind 参数如何交互,function 签名如何反映这一点?
我没有收到任何关于使用 std::bind 的积极反馈。很多关于简单使用 lambda 函数的优越结果(和代码生成),即使在这样一个简单的情况下。我自己的测试验证了这一点。
【问题讨论】:
-
不是一个答案,而是一个提示:
std::function在这里太过分了,您可以使用 lambda 代替,这也可以让您摆脱std::bind:-) -
@Acorn - 你可能是对的,但在这种情况下,在理解底层机制之前,我不禁觉得 lambda 会是另一层混淆。
-
我不太明白这些问题。你基本上是在问
std::bind和std::function是什么? -
Lambdas FTW \o/
-
here 实际上是一个骗子。我不想基本上重写那些很好的答案。我确实想让你了解情况。
标签: c++ c++11 c++17 std-function stdbind