これは、 「テンプレート内でextern-「C」関数型へのポインターをtypedefすることは可能ですか?」に対する回答のフォローアップ質問です。
g++
このコードは、Visual C / C ++、およびComeau C / C ++でコンパイルできず、基本的に同じエラーメッセージが表示されます。
#include <cstdlib>
extern "C" {
static int do_stuff(int) {
return 3;
}
template <typename return_t_, typename arg1_t_>
struct test {
static void foo(return_t_ (*)(arg1_t_)) { }
};
}
int main()
{
test<int, int>::foo(&do_stuff);
return EXIT_SUCCESS;
}
g ++は「エラー:Cリンケージのあるテンプレート」と言い、Visual C / C ++はコンパイラエラーC2894を出し、Comeau C / C ++は「エラー:この宣言には外部の「C」リンケージがない可能性があります」と言います。
事は、すべてが満足しているということです:
#include <cstdlib>
extern "C" {
static int do_stuff(int) {
return 3;
}
struct test {
static void foo(int (*)(int)) { }
};
}
int main()
{
test::foo(&do_stuff);
return EXIT_SUCCESS;
}
C ++標準のセクション7.5、リンケージ仕様は次のように述べています。
クラスメンバーの名前およびクラスメンバー関数のメンバー関数タイプについては、AC言語リンケージは無視されます。
そしてそれは例さえ与えます:
extern "C" {
class X {
void mf(); // the name of the function mf and the member
// function's type have C++ language linkage
void mf2(void(*)()); // the name of the function mf2 has C++ language
// linkage; the parameter has type pointer to C function
};
}
テンプレートが外部「C」ブロックで許可されている場合、インスタンス化のメンバー関数はC++リンケージを持ちます。
では、なぜC++98標準状態の第14章テンプレートを実行するのでしょうか。
テンプレート名にはリンケージ(3.5)が含まれる場合があります。テンプレート、テンプレートの明示的な特殊化(14.7.3)、およびクラステンプレートの部分的な特殊化には、Cリンケージがあってはなりません。
テンプレートにリンクがあるとはどういう意味ですか?テンプレートリンケージとは何ですか?
クラスに問題がなく、テンプレートのインスタンス化のすべてのメンバー関数(デフォルトのコンストラクタ、デストラクタ、および代入演算子のオーバーロード)にC ++リンケージがあるのに、Cリンケージを持つテンプレートを使用することが明示的に禁止されているのはなぜですか?