可以使用不正确的签名

时间:2015-05-13 23:54:13

标签: c++ c++11 lambda rvalue-reference

以下编译和运行(在Apple LLVM版本6.1.0和Visual C ++ 2015下):

#include <functional>
#include <iostream>

struct s { int x; };

int main(int argc, char **argv)
{
    std::function<void (s &&)> f = [](const s &p) { std::cout << p.x; };
    f(s {1});
    return 0;
}

为什么作业std::function<void (s &&)> f = [](const s &p) { std::cout << p.x; };不会产生错误?接受右值引用的函数不应该与接受const左值引用的函数具有相同的签名,如果它?从lambda声明中删除const会产生预期的错误。

2 个答案:

答案 0 :(得分:23)

扩展现有评论并回答:

{{#each play in game.plays}} {{play.date}} {{/each}} 的要点是它可以包装任何可以使用std::function<R(A...)>调用的函数或函子,并将结果存储在A...中。

所以,例如,

R

只是很好。

所以当你看到这样的东西时你必须问自己:如果你有一个lambda采用std::function<int(int)> f = [](long l) { return l; }; ,你有一个const T &类型的表达式(或者,更准确地说,你有一个类型为T &&)的xvalue,您可以使用该表达式来调用lambda吗?

是的,你可以。

如果可以,那么T应该能够存储该仿函数。这几乎是std::function的重点。

答案 1 :(得分:8)

请带上一粒盐。这是我的理解,但我不确定。

考虑以下输出:

int main(int argc, char **argv)
{
  std::cout <<  std::is_convertible<s &&, s&>::value << std::endl;       //false                                                      
  std::cout <<  std::is_convertible<s &&, const s&>::value << std::endl; //true                                                     

  std::cout <<  std::is_convertible<const s &, s&&>::value << std::endl; //false                                                     
  return 0;
}

这表明可以将s &&转换为const s&。这就是std::function的分配正常的原因。

  

从lambda的声明中删除const会产生一个   错误如预期。

确实这是因为(如前所示),将s &&转换为s &是不可能的。

以同样的方式,尝试相反:

std::function<void (const s &)> f = [](s &&p) { std::cout << p.x; };会失败,因为无法转换const s&  到s &&