21

このコードは機能しないことがわかりました。

typedef int (*fp)(int a, int b);

constexpr fp addition()
{
    return [](int a, int b){ return a+b; };
}

#include <iostream>

int main()
{
    fp fun = addition();
    std::cout << fun(2,2);
}

エラーが発生します

cexpr.cpp: In function 'constexpr int (* addition())(int, int)':
cexpr.cpp:5:43: error: call to non-constexpr function 'addition()::<lambda(int,
int)>::operator int (*)(int, int)() const'

何故ですか?ここでは呼んでいません。

直接的なアプローチは機能します:

typedef int (*fp)(int a, int b);

#include <iostream>

int main()
{
    fp fun = [](int a, int b){ return a+b; };
    std::cout << fun(2,2);
}

私はMinGWをg++バージョン4.7.2で使用しています。

4

3 に答える 3

10

関数fp()はリテラル型を返さないため、constexpr関数にすることはできません。

7.1.5以降:「constexpr関数の定義は、次の制約を満たす必要があります。

  • 仮想であってはならない(10.3)。
  • その戻り型はリテラル型でなければなりません;
  • その各パラメータ型はリテラル型でなければなりません。
  • その関数本体は、=削除、=デフォルト、または以下のみを含む複合ステートメントでなければなりません。
    • nullステートメント、
    • static_assert-宣言
    • クラスや列挙を定義しないtypedef宣言とalias-declarations、
    • using-宣言、
    • using-ディレクティブ、
    • そしてちょうど1つのreturnステートメント;"

ここにはバグはないと思います。特に、以前の回答で述べたように、ラムダに関連するものは何もありません。変数は、constexpr関数内で宣言することはできません。

于 2012-12-29T21:56:40.487 に答える
7

標準セクション5.19[expr.const]のN3376ワーキングドラフトによると:

特定のコンテキストでは、この節で詳しく説明されている追加の要件を満たす式が必要です。他のコンテキストには、式がこれらの要件を満たしているかどうかに応じて、異なるセマンティクスがあります。これらの要件を満たす式は、定数式と呼ばれます。[注:定数式は翻訳中に評価できます。—エンドノート]

それは続けて言う:

条件式は、評価される可能性のある部分式(3.2)として次のいずれかが含まれる場合を除き、コア定数式ですが、論理AND(5.14)、論理OR(5.15)、および条件付き(5.16)操作の部分式は評価されません。考慮されません[注:オーバーロードされた演算子は関数を呼び出します。—終了注]:

その下のリスト:

—ラムダ式(5.1.2);

したがって、私は十分な標準を知りませんが、これは、constexprにラムダ式を含めるべきではないと言っていると思います。

于 2012-12-29T21:53:03.847 に答える
6

gccが表示したエラーメッセージは正確で正しいものでした。

エラー:非constexpr関数の呼び出し'addition()::
             <lambda(int、int)> ::
             operator int(*)(int、int)()const '

私はそれを少し再フォーマットし、強調を加えました。ラムダを関数ポインターに強制変換することにより、自動的に作成された変換関数をラムダからに暗黙的に呼び出します。pointer to function of type "auto (int, int)->int"これは、自動作成された変換関数が宣言されていないため、constexpr関数ではありませんconstexpr(標準では、なれ)。

于 2012-12-29T22:52:36.393 に答える