std :: function与std :: bind完美结合-但是为什么呢?

Bre*_*ale 3 c++ stdbind c++11 std-function c++17

我正在使用a 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)
}
Run Code Online (Sandbox Code Playgroud)

请注意,在可移植代码允许的范围内,我尽可能彻底地播种了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);
Run Code Online (Sandbox Code Playgroud)

这非常方便,因为我使用确定性u64_prime(p)函数,(7) bases可以确定是否(p)为质数:

uint64_t p;
while (!u64_prime(p = p_dist(rng)))
    ;
Run Code Online (Sandbox Code Playgroud)

现在,我创建一个std::function对象:

std::function<uint64_t()> zp_rng = std::bind(
    decltype(p_dist){0, p - 1}, std::ref(rng));
Run Code Online (Sandbox Code Playgroud)

此函数: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的本地副本,并强制使用reference代替...因此:


:有效确定哪些基本规则是:dist(rng)被使用-我不知道为什么std::bind要强制进行这种交互。很多交互似乎基于operator ()方法。

std::functioncppreference.com上被有用地称为“通用多态函数包装器” 。那么它是封装uint64_t返回类型的函数吗?还是再次利用operator ()语法来驱动功能的概念?

尽管这些构造非常有用,但我觉得自己在某种程度上是一种狂热的编程。我正在寻找一个可以具体解决任何歧义的答案,并为类似的问题提供见解- bind期望参数如何相互作用,以及function签名如何反映这一点?


对于的使用,我没有收到任何积极的反馈std::bind。即使在这种简单情况下,也可以通过简单地使用lambda函数获得出色的结果(和代码生成)。我自己的测试验证了这一点。

inf*_*inf 6

std::bind与无关紧要std::function,它所做的只是包装可调用的内容,以便始终传递一组特定的参数,请参阅https://en.cppreference.com/w/cpp/utility/functional/bind

std::function 只接受适合您指定为其模板参数的函数签名的任何可调用对象。

std::uniform_int_distribution可调用,因为它具有operator()指定的名称,请参见https://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution/operator()。具体来说就是生成器。我们使用bind围绕它创建包装器,这样我们就不必总是显式地传递生成器。然后将结果存储在std::function匹配的uint64_t返回类型中,并且不包含任何参数(因为绑定了生成器参数)。

如果您不熟悉此概念,则应阅读有关运算符重载的信息,请参阅https://en.cppreference.com/w/cpp/language/operators(特别是函数调用运算符)。