2016-12-06 7 views
2

でキャプチャした変数を外部からのラムダで変更する方法はありますか?C++:ラムダでキャプチャした変数を外部から変更する

例:

#include <iostream> 

int main() { 
    int x = 3; 
    auto f = [x]() { std::cout << x << std::endl; }; 
    // is there anything I can do here to make f print 4? 
    f(); 
} 

これが可能であるならば、それは本当に汚い感じています。なぜそうすることを考えるべきではないのか説得力のある理由はありますか?その後

+0

あなたは代替案について考えるべきです。 'x'を参照として取り込み、それを関数のパラメータにするか、lambdasを使わないで、オーバーロードされた' operator() 'と' x' setterを持つクラスを使います。 – Rames

+1

"*私はそうすることを考えるべきではないという魅力的な理由はありますか?*"意味がないので?あなたがそうする必要があると思ったら、ラムダは何をしようとしていても間違ったツール*です。 –

答えて

1
#include <iostream> 

int main() 
{ 
    int x = 3; 
    auto f = [&x]() { std::cout << x << std::endl; }; 
    x++; 
    f(); 
} 
+0

私はそれを明確にすべきだった。私は参照としてキャプチャを認識しています - 問題は、クロージャにコピーされた変数を変更することです。 – mrks

+0

downvoteは私のものではありませんでした。その答えは、質問がもともと尋ねられた方法に対して技術的に正しいものでした。 – mrks

0
struct do_nothing{ template<class...Args> void operator()(Args&&...)const{}}; 
template<class...cmd> 
struct maybe_run_t; 
template<> struct maybe_run_t<>:do_nothing{}; 
template<class cmd>struct maybe_run_t<cmd>{ 
    cmd&& value; 
    template<class...Args> 
    void operator()(Args&&...args)const{ 
    value(std::forward<Args>(args)...); 
    } 
}; 
template<class...Args> 
maybe_run_t<Args...> maybe_run(Args&&...args){ 
    return {std::forward<Args>(args)...}; 
} 

int x = 3; 
auto f = [x](auto&&...cmd)mutable { maybe_run(cmd...)(x); std::cout << x << std::endl; }; 
// is there anything I can do here to make f print 4? 
f([](auto&x){x=4;}); 
f(); 

プリント4\n4\n

オプションの引数があります。 1つを渡すと、xが変更されます。そうしないと、コードは機能します。

また、その存在または戻り値に基づいてフロー制御を行うこともできます。

+0

IOWラムダに引数を与え、ラムダ本体で引数に基づいてxを修正する。 –

+0

@m。オプションの引数 – Yakk

0

元に戻す元の「ラムダ」タイプへ:あなたの質問に答えるためにオペレータ()

struct myLambda 
{ 
    int x; 
    myLambda(int x) : x(x) {}; 
    operator() { std::cout << x << '\n'; } 
}; 
0

で構造体やクラスを作成し、ないことは、機能/ファンクタのローカル変数を変更することはできません(ラムダとは何か)が外部からのものです。

ラムダをあなたが持っていない「普通の」関数と考えてください。通常の関数の場合と同様に、ローカル変数値を外部から変更することはできません(値渡しのパラメータ)、ラムダでも行うことはできません。これはセキュリティのために必要な要件です。結果の予測可能性は&です。

他の人が[&]シンタックスを使用することを示唆しているため、これを行う必要がある場合は問題がある場合。

(ありhttps://www.eecs.umich.edu/courses/eecs588.w14/static/stack_smashing.pdf存在しますが、私はそれがコンパイラ/システム実装の知識に依存しており、通常、未定義の動作に入ったと思います)C++ 14では

+0

名前のない関数に加えて、取得された値は[unnamed](http://en.cppreference.com/w/cpp/language/lambda)であるため、参照することができません。ラムダの体。 –

0

、あなたはこれを行うことができます:実際に

#include<iostream> 

int main() { 
    int x = 0; 
    auto l = [x]()mutable->decltype(auto){ 
     std::cout << x << std::endl; 
     return (x); 
    }; 
    l() = 42; 
    l(); 
} 

C++でも同様のことを行うのはかなり簡単です。11:

auto l = [x]()mutable->decltype(x)&{ 
    std::cout << x << std::endl; 
    return x; 
}; 

つまり、コピーによって取得された変数をref例。

関連する問題