以下行给出了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。有什么解释吗?
答案 0 :(得分:1)
它与lambdas没有任何关系。当您将函数声明为采用 const引用时,激活lifetime extension。
void foo(const std::string& ref){ . . . }
void bar(std::string& ref){ . . . }
foo(std::string("hello"));
允许 - 在foo
的整个执行过程中,包含hello的字符串的生命周期是扩展。
对于非const引用,没有这样的扩展规则,因此编译器不允许:
bar(std::string("farewell"));
因为如果确实如此,那么在foo
点开始时,它只会引用曾经是告别字符串的被破坏的残余物。
答案 1 :(得分:1)
从C ++ 11标准§20.8.11.2:
template<class R, class... ArgTypes> class function<R(ArgTypes...)> { /* ... */ }; template<class F> function(F f);
要求:
f
对于参数类型ArgTypes
应为 Callable 并返回类型R
。
在第一种情况下, Callable 表示
INVOKE(f, declval<string>(), declval<string>(), bool)
格式正确,其中f
是lambda,declval
表示string
类型的右值对象。由于rvalues不能绑定到非const左值引用,因此这里不满足此条件。
相反,rvalues可以绑定到 const lvalue references ,因此第二种情况可以。
答案 2 :(得分:0)
在你的第一个案例中,
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
这里的错误是你试图获得一个非左值的左值引用,这违反了标准。
使用function<bool(string &, string &)>
修复解决方案1(我想您可能尝试使用此版本):
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(); };
你试图得到一个对左值的恒定左值引用,这违反了标准。