正如在一个措辞类似的问题中提到的(为什么在C++14中对lambdas使用绑定?) 答案是--没有原因(并且还提到了为什么使用lambdas会更好)。
我的问题是--如果在C++14中不再有使用bind的理由,那么为什么标准委员会发现有必要在C++20中添加std::bind_front
呢?
它现在比lambda有什么新的优势吗?
bind_front
绑定了第一个X参数,但是如果可调用调用更多参数,它们就会被绑定到最后。 这使得bind_front
在只绑定函数的前几个参数时非常易读。
一个明显的例子是为绑定到特定实例的成员函数创建一个可调用函数:
type *instance = ...;
//lambda
auto func = [instance](auto &&... args) -> decltype(auto) {return instance->function(std::forward<decltype(args)>(args)...);}
//bind
auto func = std::bind_front(&type::function, instance);
bind_front
版本的噪音要小得多。 它开门见山,正好有3个命名的东西:bind_front
,要调用的成员函数和要调用它的实例。 这就是我们的情况所需要的:一个标记来表示我们正在创建一个函数的第一个参数的绑定,要绑定的函数,以及我们想要绑定的参数。 没有任何无关的语法或其他细节。
相比之下,lambda有很多我们不关心的东西。 自动。。。 args
位,std::forward
内容等。要弄清楚它在做什么有点困难,而且阅读起来肯定要长得多。
请注意,bind_front
根本不允许bind
的占位符,因此它不是真正的替换。 它更像是bind
最有用形式的速记。
提出该方法的论文简化了部分函数的应用,有一些很好的令人信服的用例。 我将在这里对它们进行总结,因为否则我将不得不引用论文的大部分内容,所以一定要去查看一下:
使用lambda将涉及std::forward
样板
在按值std::bind
和std::bind_front
存储对象的情况下,传播常量,但在捕获lambda的情况下,用户必须选择可变或常量版本,从而产生问题
使用lambda将涉及->; 用户端的decltype(auto)
样板。
与保留可变性一样,除了我们现在讨论的是lvalue/rvalue,只有std::bind_front
才正确地实现了这一点
传播可变性和保持值范畴的一个结果
这一点现在尤其重要,因为异常规范现在是类型系统的一部分
cppreference还有一些有用的注释:
此函数旨在替换std::bind。 与std::bind不同,它不支持任意参数重排,也没有对嵌套bind表达式或std::reference_wrappers进行特殊处理。 另一方面,它关注调用包装器对象的值类别,传播底层调用运算符的异常规范。