[解決済み】キャプチャしたラムダを関数ポインタとして渡す
質問
ラムダ関数を関数ポインタとして渡すことは可能でしょうか?もし可能であれば、コンパイルエラーが発生するので、何か間違ったことをしているに違いありません。
次のような例を考えてみましょう。
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
ということは、関数ポインタとして渡すことはできないのでしょうか?試しに
x
constexprも同様ですが、それは解決しないようです。
どのように解決するのですか?
ラムダが関数ポインタに変換されるのは、そのラムダが
C++11標準ドラフト
セクション
5.1.2
[expr.prim.lambda]です。
は言う (
強調
):
ラムダ式のクロージャ型 ラムダキャプチャーがない場合 があります。 public 非仮想的な非明示的な 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
はヘビーウェイト
というわけで、コスト度外視のトレードオフではありません。
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】コンストラクターでのエラー:識別子を期待されますか?
-
[解決済み】C++エラーです。"配列は中括弧で囲まれたイニシャライザーで初期化する必要がある"
-
[解決済み] string does not name a type Errorが発生するのはなぜですか?
-
[解決済み】c++でstd::vectorを返すための効率的な方法
-
[解決済み】リンカーエラーです。"リンカ入力ファイルはリンクが行われていないため未使用"、そのファイル内の関数への未定義参照
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】 while(cin) と while(cin >> num) の違いは何ですか?)
-
[解決済み】Visual Studioのデバッガーエラー。プログラムを開始できません 指定されたファイルが見つかりません
-
[解決済み】デバッグアサーションに失敗しました
-
[解決済み] 配列のベクトルを扱う正しい方法