質問

はるかに大きいプロジェクトで問題を再現する次の最小の例を考えてみましょう。

spec.h:
#include <iostream>

class A
{
public:
    template<typename T>
    T test(const std::string& a)
    {
        std::cout << "DEFAULT CALLED WITH " << a << "\n";
        return T();
    }
};
.

その他CPP:
#include "spec.h"

template<>
float A::test<float>(const std::string& a)
{
    std::cout << "SPECIAL CALLED WITH " << a << "\n";
    return float();
}
.

spec.cpp:
#include <iostream>
#include "spec.h"

int main()
{
    A a;
    a.test<int>("int");
    a.test<float>("float");
    return 0;
}
.

コンパイル:
$ make
rm -f *.o lib.a output
clang++ -g other.cpp -c
clang++ -g spec.cpp -c
ar cr lib.a other.o
clang++ -g -o output lib.a spec.o
rm -f *.o output2
clang++ -g other.cpp -c
clang++ -g spec.cpp -c
clang++ -g -o output2 other.o spec.o

$ ./output
DEFAULT CALLED WITH int
DEFAULT CALLED WITH float

$ ./output2
DEFAULT CALLED WITH int
SPECIAL CALLED WITH float
.

質問:

これはなぜ起こっているのですか?どういうわけか取り除かれていますか?lib.aと直接オブジェクトファイルの使用方法の違いは何ですか?: - )

ありがとう!

役に立ちましたか?

解決

セクション14.7.3p6:

テンプレート、メンバーテンプレート、またはクラステンプレートのメンバーが明示的に専門化されている場合、はその専門化を最初に使用する前に宣言され、暗黙のインスタンス化が行われるであろう、すべての翻訳単位でそのような使用が起こる。診断は不要です。プログラムが明示的な専門化のための定義を提供しない場合、暗黙のインスタンス化を起こさせたり、メンバーが仮想メンバー関数であることを専門とする方法で使用されたり、プログラムは診断されません。

あなたはその翻訳単位で最初に宣言することなくspec.cppの専門化を使用したので、プログラムが邪魔されています。または、次の段落は言うように:

関数テンプレート、クラステンプレート、クラステンプレートのメンバ関数、クラステンプレートのメンバ関数、クラステンプレートのメンバクラス、クラステンプレートのメンバ列挙型、メンバクラステンプレートのメンバクラステンプレート、メンバ関数のメンバクラステンプレートのクラステンプレートの配置クラステンプレートのテンプレート、クラステンプレートのメンバーテンプレートのメンバー機能、非テンプレートクラスのメンバーテンプレートのメンバ機能、クラステンプレートのメンバークラスのメンバー関数テンプレート、およびクラステンプレートの部分専門宣言の配置、メンバー非テンプレートクラスのクラステンプレート、クラステンプレートのメンバクラステンプレートなどは、明示的な専門宣言の相対的な位置と、上で指定されたように翻訳単位のインスタンス化の点に従って、プログラムが正しく形成されているかどうかに影響を与える可能性があります。以下。

専門化を書くとき
その場所には注意してください。

のAS に投票する

他のヒント

Ben Voigtの答えは正しいですが、それに少し追加したいです。

本質的に、関数の2つの異なるバージョン、other.oとspec.o(インラインテンプレートによって生成された)の2つの異なるバージョンを取得しています。リンカは1つだけを選択するように設計されており、それらが標準が必要とされていると両方とも同一であると仮定しています。最初に、シンボルがまだ定義されていない場合、リンカはライブラリから定義を引き出すだけです。Spec.oで定義されているので、ライブラリ定義は使用されていません。

ヘッダ内の定義を持つ各翻訳単位はそれ自身のインスタンス化を作成できます。したがって、あなたの専用バージョンを参照する未定義のシンボルは決してありません。それに対応して、図書館を見ると、特殊なバージョンのオブジェクトファイルは含まれていません。未定義のシンボルを定義しません。リンク中にオブジェクトファイルを明示的に含めると、リンカはそれを含める以上の選択肢がありません。ただし、すべての専門化を宣言する必要があります。このバージョンが使用されているかどうかは、シンボルの扱い方法によって異なります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top