2012-03-04 6 views
11

定数式で関数アドレスを使用する方法はありますか?関数アドレスが定数式でない理由

void foo() 
{} 

int main() 
{ 
    static_assert(&foo, "test error"); 
} 

これはコンパイルされません。

エラーC2057:定数式が期待

この背後にある意図は、私はコンパイル時に2つの関数アドレスを比較したいということです。

答えて

6

これは間違いなくコンパイラのバグです。

関数はテンプレートのテンプレート引数として使用できます。つまり、関数はconst式です。 (ideone参照)。

また、上記のコードはgcc 4.6.1で正常にコンパイルされますが、ideoneはコンパイルしませんが、ideoneはgcc-4.5.1を使用してコードに関してバグがあります。

+4

これは少し難解かもしれないと思います。関数アドレスの問題の1つは、コンパイラが必ずしもその値を知っているとは限りません(別の翻訳単位で定義されているか、まったく定義されていない可能性があります) '&fooの期待される結果(そのような表現は* odr-use *と見なされるので、コンパイラはそれを定義しなければならず、リンカがアドレスを解決できるようにすることはできません。 –

+2

関数はコンパイル時には知られていますが、アドレスはそうではありません。シンボリック名は後でリンカがメモリマップにコンパイルするときに使用されます。テンプレートはC++で導入されていますが、リンカはほとんど同じようにコンパイルされたコードを持つ関数を折りたたみ始めました。** 2つの異なる関数は実行時に同じアドレスを持つ可能性があります。**コンパイラはこれを知ることは期待されていません –

+0

S ince関数は読み込み時に再配置することができます(Windows DLLと思う)。一般に、プログラムが実行されるまで、 '&foo'がどのようにわかるのか分かりません。 –

3

これが私の理解で、FWIW:

機能タイプはコンパイル時に知られているが、機能アドレスだけリンク時に知られています。したがって、関数型をテンプレートパラメータとして使用することはできますが、アドレスはコンパイル時には定数/既知ではありません。

サンプルコードでは、コンパイラはコンパイル時にアドレスが非ゼロであると推測できますが、特定のアドレスを知ることはできません。しかし、これはコンパイラのバグではありません。

+0

アドレスはリンク時にも知られていません。コードはしばしば読み込み時に再配置されます。 –

+1

同じロード可能モジュール*内の真であるが相対アドレスは*リンク時に*認識されているので、関数ジャンプは "配線される"ことができます。私のポイントは、関数のアドレスを実行時に論理的に取ることができるということです(つまり、言語はこれが正当であることを保証します)。コンパイル時ではありません。 – Nick

関連する問題