1

テンプレートはブロック内に表示できないことを理解していextern "C"ます。その理由は、インスタンス化されたテンプレート関数の名前が、マングルされていない名前を使用して 1 回しか表示されないためです。

ただし、以下のコードでは、関数の名前マングルされています (インスタンス化ごとに一意の名前が付けられるため、問題はないはずです) が、C 言語リンケージを持つ関数型はまだあります。私の質問は、以下のコードが適切に形成されているかどうかです。

extern "C" using fn_type = void();

template<typename T>
fn_type foo;

int main()
{
    fn_type* const p = foo<int>;
    p();
}

編集: GCC、Clang、および MSVC は C++ と C 関数ポインターの型を区別しないため、コンパイラーを介して実行するだけでは、これが準拠しているかどうかをテストするのは困難です。

4

1 に答える 1

1

私には、この基準が 100% 明確ではないように思えます。テンプレートとリンケージに言及している唯一の関連部分は、C++11 の [temp]§4 です。

テンプレート名にはリンケージ (3.5) があります。非メンバー関数テンプレートは、内部リンケージを持つことができます。他のテンプレート名には、外部リンケージが必要です。内部リンケージを持つテンプレートの特殊化 (明示的または暗黙的) は、他の翻訳単位のすべての特殊化とは異なります。テンプレート、テンプレートの明示的な特殊化 (14.7.3)、およびクラス テンプレートの部分的な特殊化には、C リンケージがあってはなりません。C または C++ 以外のリンケージ仕様とこれらの構成のいずれかの使用は、実装定義のセマンティクスで条件付きでサポートされます。[...]

(私のものを強調)

パラグラフは、リンケージを持つテンプレート名で始まります。次に、「関数テンプレート は内部リンケージを持つことができます。他のテンプレートは外部リンケージを持つ必要があります」と表示されます。(notname)

私には、これは、テンプレートのリンケージを参照することは、テンプレートの名前のリンケージを参照することを意味しているようです。その解釈が正しい場合、太字の部分はテンプレートにも適用されるため、例は整形式です。その場合、関数テンプレート型が C リンケージを持つことを妨げるものは何もありません。

それが私が標準を解釈する方法です。

于 2013-10-18T11:52:35.513 に答える