キャプチャラムダを関数ポインタとして渡す 質問する

キャプチャラムダを関数ポインタとして渡す 質問する

ラムダ関数を関数ポインターとして渡すことは可能ですか? もし可能であれば、コンパイル エラーが発生するので、何か間違ったことをしているに違いありません。

次の例を考えてみましょう

using DecisionFn = bool(*)();

class Decide
{
public:
    Decide(DecisionFn dec) : _dec{dec} {}
private:
    DecisionFn _dec;
};

int main()
{
    int x = 5;
    Decide greaterThanThree{ [x](){ return x > 3; } };
    return 0;
}

私がこれをコンパイルしてみてください、次のコンパイル エラーが発生します。

In function 'int main()':
17:31: error: the value of 'x' is not usable in a constant expression
16:9:  note: 'int x' is not const
17:53: error: no matching function for call to 'Decide::Decide(<brace-enclosed initializer list>)'
17:53: note: candidates are:
9:5:   note: Decide::Decide(DecisionFn)
9:5:   note: no known conversion for argument 1 from 'main()::<lambda()>' to 'DecisionFn {aka bool (*)()}'
6:7:   note: constexpr Decide::Decide(const Decide&)
6:7:   note: no known conversion for argument 1 from 'main()::<lambda()>' to 'const Decide&'
6:7:   note: constexpr Decide::Decide(Decide&&)
6:7:   note: no known conversion for argument 1 from 'main()::<lambda()>' to 'Decide&&'

これは理解するのが非常に難しいエラー メッセージですが、私が理解しているのは、ラムダを関数ポインターとして扱うことができないconstexprため、関数ポインターとして渡すことができないということだと思います。constexpr も作成してみましたxが、役に立たないようです。

ベストアンサー1

ラムダは、関数ポインタに変換できるのは、C++11標準草案セクション5.1.2 [expr.prim.lambda]には次のように書かれています (強調は筆者による):

ラムダキャプチャのないラムダ式のクロージャ型には、クロージャ型の関数呼び出し演算子と同じパラメータと戻り値の型を持つ関数へのポインタへの、パブリックな非仮想非明示的 const 変換関数があります。この変換関数によって返される値は、呼び出されると、クロージャ型の関数呼び出し演算子を呼び出すのと同じ効果を持つ関数のアドレスになります。

注意:cppreferenceのセクションでもこれについて触れています。ラムダ関数

したがって、次の代替案が機能します。

typedef bool(*DecisionFn)(int);

Decide greaterThanThree{ []( int x ){ return x > 3; } };

そしてこれも同様です:

typedef bool(*DecisionFn)();

Decide greaterThanThree{ [](){ return true ; } };

そして5gon12eder指摘しているように、std::functionただし、std::function重量が重いしたがって、コストゼロのトレードオフではありません。

おすすめ記事