5

ご存知のように、非キャプチャ ラムダ ファンクターは実行時に関数ポインターに変換できますが、コンパイル時はどうでしょうか。つまり、以下のコードに似たものは可能ですか? ラムダファンクターを関数パラメーターとして渡すなどの回避策を提案しないでください。C++ 11標準がこれを禁止している場所/方法をもっと知りたいです。

template <void(*fptr)()>
void f()
{
  // do something
}

int main()
{
  auto l([]{});

  f<(void(*)())(decltype(l))>();

  return 0;
}

の必須エラーgcc-4.8:

c.cpp: In function 'int main()':
c.cpp:11:7: error: parse error in template argument list
       f<(void(*)())(decltype(l))>();
       ^
c.cpp:11:36: error: statement cannot resolve address of overloaded function
       f<(void(*)())(decltype(l))>();
                                    ^
4

1 に答える 1

2

ラムダ式は、空のクロージャーであっても、関数テンプレート引数へのポインターとして使用することはできません。これは、たまたま関数へのポインターに変換される一時的なものであるためです。ラムダ式は、5.1.2 [expr.prim.lambda] パラグラフ 2 に従って一時的なものです。

ラムダ式の評価は、一時的な prvalue になります。[...]

関数へのポインタへの変換は、段落 6 で説明されています。

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

つまり、変換によって a が生成されないためconstexpr、関数への結果のポインターをテンプレート引数として使用する見込みはありません。

理由については、 N3597 の中で、実際の問題について話しているように見える N2895 を指し示しているのが最善の理由ですが、詳細な議論を見つけることができませんでしラムダ式によって作成された関数の名前マングリングは、特定のコンテキストでの使用を禁止する問題の 1 つと思われます。

于 2013-12-22T21:36:11.013 に答える