10

同じコードのコンパイルとリンクで MSVC と GCC (おそらく clang も) の不一致を発見した後、このプログラムが実際にコンパイルしてリンクする必要があるかどうかに興味を持ちました。私はそれを別の方法で書きます。プログラムは次の 3 つのファイルで構成されます。

チャンネル

template <typename T>
struct A
{
    void func() {};
};

template <>
void A<int>::func ();

A.cpp:

#include "C.h"
int main()
{
    A<int> x;
    x.func();
}

B.cpp:

#include "C.h"
template <>
void A<int>::func()
{
}

MSVC からの結果のリンカー エラーは次のとおりです。

A.obj : エラー LNK2019: 未解決の外部シンボル "public: void __thiscall A::func(void)"

したがって、基本的には、に配置された定義からシンボルを作成しないことにしますB.cpp。バグとして強く疑うのは、特殊化されていない定義funcを構造体定義の外に移動し、特殊化宣言の上に配置することでプログラムのリンクが成功することですが、確認したいと思います。

だから私の質問は - このプログラムは、準拠したコンパイラ/リンカーによってエラーなしでコンパイルおよびリンクされるべきですか?

4

2 に答える 2

1

標準から:

© ISO/IEC N4527 14.6.4.1 インスタンス化のポイント [temp.point] 1 関数テンプレートの特殊化、メンバー関数テンプレートの特殊化、またはクラス テンプレートのメンバー関数または静的データ メンバーの特殊化の場合、特殊化が暗黙的に行われる場合別のテンプレートの特殊化内から参照され、それが参照されるコンテキストがテンプレート パラメーターに依存するため、インスタンス化されます。特殊化のインスタンス化のポイントは、囲んでいる特殊化のインスタンス化のポイントです。それ以外の場合、そのような特殊化のインスタンス化のポイントは、その特殊化を参照する名前空間スコープの宣言または定義の直後に続きます

この場合、これは「スコープ宣言」が発生する Ch を意味すると思います。この場合、コードは標準準拠のツール チェーンとリンクする必要があります。私はこれを誤解している可能性があります...

于 2015-09-06T12:25:49.630 に答える
-2

名前のない名前空間には内部リンケージがあります。テンプレートの特殊化は名前のない名前空間内にあるため、内部リンケージもあります。

この問題を解決するには、テンプレートを名前付きの名前空間に配置するか、特殊化を「extern」として指定します。

于 2015-09-06T17:16:52.473 に答える