【问题标题】:Why is there a difference between std::function constructor or assignment?为什么 std::function 构造函数或赋值之间有区别?
【发布时间】:2016-09-13 13:31:21
【问题描述】:

std::function 类型擦除构造函数定义为:

template< class F >
function( F f );

赋值运算符定义为:

template< class F >
function& operator=( F&& f );

(源 cppreference)

为什么构造函数通过值获取f,而operator=通过转发引用获取f

【问题讨论】:

标签: c++ c++11 std-function perfect-forwarding


【解决方案1】:

我只能猜测,但我猜这是因为它被添加到 C++ 中,而右值引用和转发引用被添加到语言中。

所以其 API 的某些部分获得了转发引用,而有些则没有。

有一个小优势:如果F的复制构造函数可以抛出而移动不能,则std::function( F )可以保证不抛出,而std::function( F const&amp; )不能。不同之处在于,在template&lt;class F&gt; function(F) 情况下,复制将在构造函数之外完成,但在template&lt;class F&gt; function(F&amp;&amp;) 情况下,当传递非右值时,复制将在构造函数内部完成。

这不是一个令人信服的理由。

这也使得指定function(F) 的 SFINAE 行为稍微容易一些,但直到 C++11 很久之后才正式化,所以这不是原因。

template&lt;class F&gt;function(F) 的成本很低——F 比完美转发版本的成本低——所以它可能在任何人的优先级列表中都不高(尤其是因为它会导致“可能会抛出”function(F) 的测试,因此理论上实际上可能会导致一些奇怪的代码中断)。

【讨论】:

  • 但如果是这样,为什么 std::function::assign 在 C++17 中被弃用但构造函数的签名没有改变?这意味着有人确实考虑过改进 std::function API,但是,他们没有改变 copy-the-callable-constructor
猜你喜欢
  • 2012-07-27
  • 1970-01-01
  • 2019-05-11
  • 1970-01-01
  • 2012-05-07
  • 2015-07-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多