簡體   English   中英

不能使用顯式類型的lambda

[英]Cannot use explicitly typed lambda

我有這個代碼:

std::function<std::string&(std::string&)> change_str = [](std::string& str){
    return (str = "Hello world!");
};

std::string s;

std::cout << change_str(s) << std::endl;

它沒有編譯,並說:

main.cpp:8:47: error: no viable conversion from '(lambda at main.cpp:8:60)' to 'std::function<std::string &(std::string &)>'
    std::function<std::string&(std::string&)> change_str = [](std::string& str){
                                              ^            ~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/v1/functional:1448:5: note: candidate constructor not viable: no known conversion from '(lambda at main.cpp:8:60)' to 'nullptr_t' for 1st argument
    function(nullptr_t) _NOEXCEPT : __f_(0) {}
    ^
/usr/include/c++/v1/functional:1449:5: note: candidate constructor not viable: no known conversion from '(lambda at main.cpp:8:60)' to 'const std::__1::function<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > &(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > &)> &' for 1st argument
    function(const function&);
    ^
/usr/include/c++/v1/functional:1450:5: note: candidate constructor not viable: no known conversion from '(lambda at main.cpp:8:60)' to 'std::__1::function<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > &(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > &)> &&' for 1st argument
    function(function&&) _NOEXCEPT;
    ^
/usr/include/c++/v1/functional:1454:41: note: candidate template ignored: disabled by 'enable_if' [with _Fp = (lambda at main.cpp:8:60)]
                                        __callable<_Fp>::value &&
                                        ^
main.cpp:8:60: note: candidate function
    std::function<std::string&(std::string&)> change_str = [](std::string& str){
                                                           ^
1 error generated.

但是,如果我將std::function的聲明更改為auto ,那么它的工作原理如下:

auto change_str = ...

為什么顯式類型不適用於lambda?

沒有返回類型的lambda是auto ,並且自動刪除外部引用,因此您不返回string&而只是string

只需聲明功能為

std::function<std::string&(std::string&)> change_str = 
[](std::string& str) -> string&  ///<--- NOTE THIS
{
    return (str = "Hello world!");
};

lambda的deduced返回類型是std::string ,這就是你的聲明不匹配的原因。 但是當您明確指定返回類型時,它可以工作:

std::function<std::string&(std::string&)> change_str = 
        [](std::string& str) -> std::string& 
{
    return (str = "Hello world!");
};

正如其他人說,這個問題是默認的返回類型推演推導std::string這是不符合預期的兼容std::string&

解決此問題的各種聲明的目錄:

// be completely explicit about the return type
[](std::string& str) -> std::string& {

 // be explicit about returning lvalue reference
[](std::string& str) -> auto& {

// be explicit that you're returning some kind of reference type,
// but use reference collapsing to determine if it's an lvalue or rvalue reference
[](std::string& str) -> auto&& { 

// use C++14 feature to deduce reference type
[](std::string& str) -> decltype(auto) {

這些按最少到最通用的順序列出。 但是在這種情況下,並不特別需要通用性:您只是推斷返回類型,因為這是默認/最少打字。 其中我可能會說明確可能是最好的: [](std::string &str) -> std::string& {

quantdev刪除了他的答案,我認為這是另一個好建議:

[](std::string& str) {
    return std::ref(str = "Hello world!");
};

這是有效的,因為std::function只需要對參數和返回類型進行適當的可轉換,並且返回std::ref結果符合該要求。

使用std::ref和使用顯式的std::string & return類型對我來說都是可讀的。 對我的實現進行優化會為兩者產生完全相同的東西,所以如果你更喜歡std::ref的外觀,那么沒有理由不使用它。

沒有返回類型的lambda表現為auto遵循Template Argument Deduction規則,你的返回類型推斷為std::string而不是std::string&

如果明確指定了類型,一切都很好

std::function<std::string&(std::string&)> change_str = 
                                 [](std::string& str) -> std::string& {
  return (str = "Hello world!");
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM