PG日誌

受託系 PG が C# の事を書いています

C#とC++でラムダ式を利用、運搬性を確認する

C++11からC++でもラムダ式が使用できるようになったので、今更ですが使い勝手と、運搬性ををC#を比べてみました。ラムダ式を使用する方法と、変数に入れて持ち運ぶ方法の2とおりの使い方を確認しています。

C#でラムダを使用・運搬する

最初はC#です。かなり簡潔に書けます。これ以上の指定は存在しません。

public class CSharpClass
{
    private flag;
    private Func<bool(int)> method;
    
    // 単純な呼び出し
    public Func<bool> GetLambda(int a)
    {
        return () => this.flag;
    }
    
    // ラムダへローカルメンバーを設定
    public void SetLambda()
    {
        this.method = this.getFlag;
        
        // もしgetFlagがstaticメソッドだったら以下の通り
        // (クラス内ならクラス名修飾しなくてもよい)
        this.method = CSharpClass.getFlag;
    }
    
    private bool getFlag(int a) { return true; }
}

C++でラムダを使用・運搬する

次はC++です。インスタンスメソッドの場合特別な指定が必要です。

class CppClass
{
    bool flag;
    std::function<bool()> method;
    
public:
    
    std::function<bool()> getFlag()
    {
        return [this]()
        {
            // VisualStudio2017だと->を入力しても
            // privateメンバーがインテリセンスに表示されない(?)けど
            // 普通にメンバー名を手打ちすれば使用可能
            return this->flag;
        }
    }
    
    void SetLambda()
    {
        // フリー関数
        this->method = getFlagFree;

        // クラスのメンバー関数
        this->method = std::bind(&CppSample::getFlagLocal, this, std::placeholders::_1);

        // クラスのStatic関数を設定する場合
        std::function<bool()> method = CppClass::methodByStatic;
        
        // ↑と意味は同じ(つまり無意味)
        this->method = std::bind(&CppSample::getFlagStatic, std::placeholders::_1);
        
        // こうするとthis->method(100)とかしても5で関数が呼ばれる
        this->method = std::bind(&CppSample::getFlagStatic, 5);
    }
}

見ての通り、C++のほうが言語使用が多い&古いので使用がやや複雑です。が、今までの事を考えるとこれでもかなり進化していると見れます。

C#の方が指定が完結ですが、C++はbindを使用し、1層噛ましている形になるので、placeholdersの代わりに実数を指定して引数を固定する事ができます。ただし若干不可解な動きにはなりますが…