【问题标题】:C++ lambda to std::function error with non const strings带有非 const 字符串的 C++ lambda 到 std::function 错误
【发布时间】:2018-01-28 18:25:47
【问题描述】:

以下行在 c++ 11 中给出错误:

function<bool(string,string)> comp = [] (string& s1, string& s2) {return s1.length() > s2.length(); };

但事实并非如此:

function<bool(string,string)> comp = [] (const string& s1, const string& s2) {return s1.length() > s2.length(); };

第二次调用的参数为 const。有什么解释吗?

【问题讨论】:

  • 临时对象或文字不能绑定到对非常量对象的引用。 Any good beginners book 应该告诉你的。
  • 右值(比如传值的参数)不能绑定到非const左值引用,但是可以绑定到const左值引用。
  • 你知道自动对 lambda 有效吗? auto comp = ...

标签: c++ c++11 lambda


【解决方案1】:

它与 lambdas 没有任何关系。当您将函数声明为采用 const 引用 时,您将激活 lifetime extension

void foo(const std::string& ref){ . . . }
void bar(std::string& ref){ . . . }

foo(std::string("hello")); 

允许 - 包含 hello 的字符串的生命周期在foo 的整个执行过程中延长

对于非常量引用,没有这样的扩展规则,所以编译器不会允许:

bar(std::string("farewell")); 

因为如果确实如此,在foo 开始时,它只会引用曾经是告别字符串的被破坏的残余物。

【讨论】:

    【解决方案2】:

    来自 C++11 标准第 20.8.11.2 节:

    template<class R, class... ArgTypes>
    class function<R(ArgTypes...)> { /* ... */ };
    
    template<class F> function(F f);
    

    要求:f 对于参数类型 ArgTypes 应该是可调用 并返回类型R

    在您的第一种情况下,Callable 意味着

    INVOKE(f, declval<string>(), declval<string>(), bool)
    

    格式正确,其中f 是 lambda,declval 表示 string 类型的右值对象。由于右值不能绑定到非常量左值引用,所以这里不满足这个条件。

    相反,右值可以绑定到const左值引用,所以第二种情况是可以的。

    【讨论】:

      【解决方案3】:

      在您的第一种情况下,

      function<bool(string,string)> comp = [] (string& s1, string& s2) {return s1.length() > s2.length(); };
      

      你正在尝试编译这样的东西:

      bool comp(string& s1, string& s2){/*...*/}
      comp(string(), string());//passing a lvalue reference to a rvalue 
      

      这里的错误是您试图获取对右值的非常量左值引用,这违反了标准。

      修复解决方案1,使用function&lt;bool(string &amp;, string &amp;)&gt;(我想你可能正在尝试使用这个版本):

      function<bool(string&,string&)> comp = [] (string& s1, string& s2) {return s1.length() > s2.length(); };
      

      解决方案 2,使用右值引用:

      function<bool(string,string)> comp = [] (string&& s1, string&& s2) {return s1.length() > s2.length(); };
      

      在第二种情况下,

      function<bool(string,string)> comp = [] (const string& s1, const string& s2) {return s1.length() > s2.length(); };
      

      您正试图获取对右值的 const 左值引用,这不违反任何标准。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-07-12
        • 1970-01-01
        • 2014-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-20
        相关资源
        最近更新 更多