2

特殊化された明示的にインスタンス化されたテンプレート クラスがあります。

// a.hh
#pragma once

template<int N>
struct A {
  int foo();
};

// a.in
#include "a.hh"

template<>
int A<1>::foo() { return 1; } // specialization for N=1

template<>
int A<2>::foo() { return 2; } // specialization for N=2

// a1.cc
#include "a.in"

template struct A<1>; // explicit instantiation for N=1

// a2.cc
#include "a.in"

template struct A<2>; // explicit instantiation for N=2

上記のファイルは、g++ 4.9.2 でスタティック ライブラリにコンパイルされます。

g++ -Wall -c -o a1.o a1.cc
g++ -Wall -c -o a2.o a2.cc
ar rcs libtest.a a1.o a2.o

a1.o には A<1>::foo() が含まれ、a2.o には A<2>::foo() が含まれていると思いますが、その逆ではありません。 .cc ファイル。

ただし、両方のオブジェクト ファイルに両方の関数が含まれていることがわかります。VS2015RC はリンカの警告も表示します。

a1.obj : warning LNK4006: "public: int __thiscall A<1>::foo(void)" already defined in a2.obj; second definition ignored
a1.obj : warning LNK4006: "public: int __thiscall A<2>::foo(void)" already defined in a2.obj; second definition ignored

なんで?

また、N=2 の特殊化をコメント アウトすると、明示的にインスタンス化された N=2 のケースに未解決の関数があるにもかかわらず、g++ を使用してサイレントにコンパイルされます... (VS2015RC は、「明示的なテンプレートのインスタンス化要求に対して適切な定義が提供されていません」と警告します"、 予想通り)。


明確化- 標準 (14.7.3.6) によると:

[..] クラス テンプレートのメンバーが明示的に特殊化されている場合、その特殊化は、そのような使用が発生するすべての翻訳単位で、暗黙的なインスタンス化を引き起こす特殊化の最初の使用の前に宣言されなければなりません[.]

この一節は、インスタンス化するためには特殊化の使用が必要であることを (暗黙のうちに) 述べています。

私の問題は、その翻訳単位でこの仕様が使用されていないにもかかわらず、 A<2>::foo() が a1.o で暗黙的にインスタンス化されることです。

4

2 に答える 2

2

あなたの専門は ではありませんinlineしたがって、 a.inを含む翻訳単位ごとに1つの定義があります。

inlineキーワードを追加:

template<>
inline int A<1>::foo() { return 1; } // specialization for N=1

または cpp ファイルの定義を移動します。

// a1.cc
#include "a.hh"

template<>
int A<1>::foo() { return 1; } // specialization for N=1

template struct A<1>; // explicit instantiation for N=1
于 2015-07-10T14:50:54.590 に答える
1

あなたのコードは

template<>
int A<1>::foo() { return 1; } // specialization for N=1

これはメンバー関数の明確な定義であるため、2 回実行することはできません。したがって、 が 1 つの翻訳単位内にあることを確認してください。

14.7.3 明示的な特殊化

5 明示的に特殊化されたクラスのメンバーは、クラス テンプレートのメンバー宣言から暗黙的にインスタンス化されません。代わりに、その定義が必要な場合は、クラス テンプレートの特殊化のメンバー自体を明示的に定義する必要があります。

于 2015-07-10T14:58:51.667 に答える