2016-07-27 58 views
20

說我有一個包含拉姆達以下變量:C++ 11將`auto` Lambda更改爲不同的Lambda?

auto a = [] { return true; }; 

而且我想a稍後返回false。我能做些什麼嗎?

a = [] { return false; }; 

這句法給了我以下錯誤:

binary '=' : no operator found which takes a right-hand operand of type 
'main::<lambda_a7185966f92d197a64e4878ceff8af4a>' (or there is no acceptable conversion) 

IntelliSense: no operator "=" matches these operands 
     operand types are: lambda []bool()->bool = lambda []bool()->bool 

有沒有辦法實現這樣的事情?我想將auto變量更改爲不同的lambda。我是一個初學者,所以我可能會錯過auto或lambda的一些知識。謝謝。

+2

有'bool b = true; auto a = [&b] {return b; }; b = false;'解決方案,但這當然不會推廣到所有情況。 – MSalters

回答

31

每個lambda表達式創建一個新的獨特的類型,所以你的第一拉姆達的類型是從你的第二個(example)的類型不同。此外,lambda的複製賦值操作符被定義爲刪除(example),所以您雙重無法執行此操作。對於類似的效果,你可以有astd::function對象,雖然它會花費你一些性能

std::function<bool()> a = [] { return true; }; 
a = [] { return false; }; 
32

拉姆達可以使用一元+運營商,像這樣被轉化爲一個函數指針:

+[]{return true;} 

只要捕獲組是空的並且它沒有auto參數。

如果您這樣做,只要lambda表達式都具有相同的簽名,您就可以將不同的lambda表分配給相同的變量。

在你的情況,

Live example on Coliru

將編譯和行爲像您期望的。 您可以像使用lambda一樣使用函數指針,因爲兩者都會作爲functors


1.在C++ 14,可以用auto作爲參數類型聲明的lambda一樣[](auto t){}。這些是generic lambdas,並且具有模板operator()。由於函數指針不能表示模板函數,所以+技巧不適用於通用lambda表達式。

2.從技術上講,您不需要在作業上使用第二個+操作符。 lambda會在賦值時轉換爲函數指針類型。不過,我喜歡這種一致性。

+10

C++正式進入Perl領域的那一刻! – peppe

+0

@jaggedSpire我需要這麼多次這麼糟糕,我認爲唯一的解決方案是其他'功能'解決這個問題。你是怎麼知道這件事的?我從來沒有見過它。 –

+0

@JonathanMee我實際上發現它從下面的側邊欄中的相關鏈接,曾經一次:[積極的lambda:'+ [] {}' - 這是什麼巫術?](http://stackoverflow.com/questions/18889028) – jaggedSpire

4

每個拉姆達有不同的類型,因此你不能改變它。您可以使用std::function來保存任意可調用的對象,可以隨意更改。

std::function <bool()> a = [] { return true; }; 
a = [] { return false; }; 
+0

我猜Ryan在發佈同樣的東西的時候打敗了你。但是你錯過了一個分號。 –

1

我們可能會使用retrospective call轉換拉姆達爲std ::功能:

template<typename T> 
struct memfun_type 
{ 
    using type = void; 
}; 

template<typename Ret, typename Class, typename... Args> 
struct memfun_type<Ret(Class::*)(Args...) const> 
{ 
    using type = std::function<Ret(Args...)>; 
}; 

template<typename F> 
typename memfun_type<decltype(&F::operator())>::type 
FFL(F const &func) 
{ // Function from lambda ! 
    return func; 
} 

在此之後,我們將能夠做到(因爲 'A' 是的std ::功能類型現在):

auto a = FFL([] { return false; }); 
a = FFL([] { return true; }); 
+0

多一點解釋會很好。 –

0

由於C++17你可以有std::function模板參數推導感謝Class template argument deduction。它甚至適用於捕獲lambdas:

int a = 24; 

std::function f = [&a] (int p) { return p + a; }; 
f    = [&a] (int p) { return p - a; }; 
f    = [] (int p) { return p; }; 

這適用於更復雜的簽名和更多的推導返回類型。