通常の関数では、次のように書くことができます
extern "C" int Frotz(int); // in a header
int Frotz(int x) { return x; }
ただし、関数ポインターでは、これはコンパイラー間で矛盾して実装されているようです。
extern "C" int Klutz(int (*)(int), int);
int Klutz(int (*fptr)(int), int x) { return (*fptr)(x); }
宣言では、引数もextern "C"
です。定義では、ほとんどのコンパイラはこれらの関数に一致して関数を作成しているように見えKlutz
ますextern "C"
。ただし、Sun および Cray コンパイラはこれらの関数を異なるものとして解釈し、オーバーロードint Klutz(int (*fptr)(int), int x)
された を生成し、後でリンク時エラーを生成します。
C++98 および C++11 のセクション 7.5.5 では の解釈が保証されていますが、オーバーロードのチェックの前または後にマッチングを行うべきFrotz
かどうかについて、標準が曖昧であるかどうかはわかりません。extern "C"
Klutz
上記はマングル (C++) シンボルまたはシンボルを生成する必要がありextern "C"
ますか?
編集1
C または C++ ABI を持つ関数ポインターのあいまいさを解消するために typedef を使用できますが、ここでのコードが (a) Klutz
C++ リンケージを持つように定義するか、(b) C リンケージを持つように定義するか、または (c)標準によればあいまいなので、コンパイラはそれを解釈する方法を自由に選択できます。
編集2
これは、少なくとも検索可能なバグ トラッカーを備えたコンパイラでは、既知の問題のようです。私のテストでは、GCC、Clang、Intel、MSVC、IBM XL、PathScale、PGI、および Open64 はすべて、標準で明示的に要求されているように、言語リンケージを除いて同一の関数型を区別できません (セクション 7.5.1 を参照してください。受け入れられた答え)。これを修正すると、多くの既存のコードが壊れ、ABI の変更が必要になります。C言語とC++言語のリンケージに異なる呼び出し規約を実際に使用しているコンパイラは知りません。