2016-03-31 8 views
2

ラムダ関数に固有の変数を作成する方法はありますか?
もっと慎重説明:私はいくつかの値に初期化変数とラムダをしたい、そしてその変数が起動の間続く必要があります。ラムダ固有の変数

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

だから、これは01

をプリントアウトする必要がありますしかし、また、私は、「それを確認する必要があり前の部分の後に、この

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

は、私が試した01

をプリントアウトする必要がありますので、Xは、 『A」のためのユニークな』静的変数を使用していますが、それらはコピー間で共有されています(したがって、これら2つの部分は0123を出力します)。

だから、それを行う方法はありますか?

+1

なぜ複雑ですか?あなたはクラスを書くことができませんか? – jrok

+0

私は多少複雑なクラスのシステムを持っていますが、そのうちの1つは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には、簡単:アウト01

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

プリントを。 C++ 11では

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

それも動作しますが、もう少し醜いです。

ラムダの外部にあるXのコピーを除き、C++ 11のバージョンは動作のC++ 14のバージョンと同じです。

live example

+1

私はOPが望んでいるものとまったく同じだとは思わない。さて、この部分をa()の後に追加してください。 a(); "自動b = a; b(); b()"。 OPは、質問の私の読書に基づいて、bのカウンタをリセットしたい。 –

+0

OPは、関数オブジェクトがコピーされたときにメンバをリセットしたい。 – jrok

+0

@ SAMああ、その奇妙なことを逃した。それを実現するためにタイプが追加されました。 – Yakk

3

私は可変ラムダが十分であるとは思いません。ファンクションポインタをコピーし、カウンタもコピーすると、変更可能なキャプチャがコピーされます。質問の私の読んで、ラムダの各コピーは、最初の変更キャプチャで開始する必要があります。

あなたがこれを行うには、コピーコンストラクタで、カスタムクラスをキャプチャする必要があります。

#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のみがaを生成します


私の質問は、以前のb救いが望まれる。

+0

クラスメンバーが変更可能であると宣言されている場合、ラムダ自身が変更可能なキャプチャを使用する必要はありません。これを確認するにはあまりにも怠惰ですが、私の右の音です... –

0

唯一のオプションを「リセット」するためにコピーコンストラクタを使用していますか?代わりに、同じ初期環境から新鮮なラムダを放つファクトリ関数を書くべきではありませんか?

コピーがセマンティクスを乱用した後、スタッフ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'をコピーしたときに、カウンタを自動的にリセットする必要があります。それが「セマンティクスの乱用」であろうとなかろうと、それはややポイントの横にある。おそらくそれはそうではないかもしれません。誰かが主張しているかもしれません。しかし、興味深い技術的な質問ですが、それはそのメリットに有効です。 –

+0

@SamVarshavchik「質問に明白に必要です」 - わかっています。 OPが自殺の方法に関するアドバイスを求めた場合、そのアドバイスを提供しますか?あるいは、あなたは彼にそれをしないように伝えたいですか?私が避けたいのは、XY問題のYに答えることだけです。 –

+0

技術的な質問と自殺とを比較することは少しばかり進んでいます。 –

関連する問題