2016-03-31 33 views
2

有沒有什麼辦法可以創建對某些lambda函數來說是唯一的變量,並且會在啓動lambda之間持續?
更仔細的描述:我想初始化一些值變量拉姆達,和該變量應該持續推出之間:特定於lambda的變量

std::function<void(void)> a=[]() 
{ 
    /*here we declare variable X and initialize it to 0*/; 
    std::cout<<X++; 
}; 
a();a(); 

所以這應該打印出01

而且我需要確保「 X」是獨特的‘一’,所以前面的部分在此之後

std::function<void(void)> b=a; 
b();b(); 

應該打印出01

我試着使用靜態變量,但它們之間共享副本(所以這兩部分打印出0123)。

那麼,有沒有辦法做到這一點?

+1

爲什麼會變得複雜?你不能寫一個班嗎? – jrok

+0

我有一些類的複雜系統,其中一個使用lamdas作爲用戶定義的自定義函數。我想避免使用抽象類來實現這些功能的數據存儲。而且這個類的對象也可以被複制,所以像靜態變量這樣的簡單解決方案不起作用。 – jammer312

+0

這種打破「複製」的含義。 – Barry

回答

2

您希望它在複印時重置。做,做這樣的數據:

template<class T> 
struct no_copy { 
    T init; 
    T current; 
    operator T&(){ return current; } 
    operator T const&()const{ return current; } 
    no_copy(T&& i):init(i), current(init) {} 
    no_copy(no_copy const&o):init(o.init), current(init) {} 
    no_copy(no_copy &&o):init(std::move(o.init)), current(init) {} 
}; 
template<class T> 
no_copy<std::decay_t<T>> make_no_copy(T&& t){ 
    return {std::forward<T>(t)}; 
} 

然後,在C++ 14,容易:

std::function<void(void)> a=[X=make_no_copy(0)]()mutable 
{ 
    std::cout<<X++; 
}; 
a();a(); 

打印出01

在C++ 11:

auto X=make_no_copy(0); 
std::function<void(void)> a=[X]()mutable 
{ 
    std::cout<<X++; 
}; 
a();a(); 

它也可以,但有點更醜。

除了在lambda外部存在的X的副本之外,C++ 11版本與C++ 14版本的行爲相同。

live example

+1

我不認爲這正是OP想要的。現在,在()後添加這個部分;一個(); 「auto b = a; b(); b()」。根據我對問題的閱讀,OP希望b的計數器重置。 –

+0

OP要複製函數對象時復位成員。 – jrok

+0

@sam啊,錯過了那個怪癖。添加類型以實現此目的。 – Yakk

3

我不認爲可變lambda表達式就足夠了。當您複製函數指針時,可變捕獲將被複制,同時複製計數器。我讀到的問題是,lambda的每個副本應該從最初的可變捕獲開始。

您需要捕獲一個自定義的類,它有一個拷貝構造函數,要做到這一點:

#include <functional> 
#include <iostream> 

class my_class { 

public: 
    int n=0; 

    my_class() 
    { 
    } 

    my_class(const my_class &b) 
    { 
    } 
}; 

int main() 
{ 

    std::function<void(void)> a= 
     [my_class_instance=my_class()]() 
     mutable 
     { 
      std::cout << my_class_instance.n++; 
     }; 
    a(); 
    a(); 

    auto b=a; 

    b(); 
    b(); 

} 

從這樣的結果是:

0101 

沒有一個輔助類,使用等效代碼只有可變的lambda會產生一個


我讀到的問題是,前者b行爲是需要的。

+0

如果類成員被聲明爲可變,那麼你甚至不需要讓lambda本身使用可變捕獲。太懶惰,以確認這一點,但聽起來對我來說,太... –

0

正在使用複製構造函數進行「重置」唯一選項?你不應該寫一個工廠函數,從相同的初始環境中發出新鮮的lambda表達式嗎?

在複製濫用語義之後,期望那個東西A與東西B不同。

auto make_counter() -> std::function<int()> { 
    return [x=0]() mutable { return x++; }; 
} 

auto a = make_counter(); 
std::cout << a() << " " << a() << "\n"; 

auto b = make_counter(); 
std::cout << b() << " " << b() << "\n"; 
+0

這個問題明確要求計數器自動重置,當類型擦除的'std :: function'被複制,而不是構造另一個lambda實例。不管它是否「濫用語義」,或者不是,都有點不合適。也許是,也許不是,這是爲了別人爭論。但是,這是一個有趣的技術問題,它的優點是有效的。 –

+0

@SamVarshavchik「這個問題明確要求」 - 我知道。如果OP詢問有關如何自殺的建議,您是否會提供這些建議?或者你寧願告訴他不要這樣做?我想要阻止的是回答XY問題的Y. –

+0

比較一個技術問題與自殺有點牽強。 –