6

テンプレートクラスをで宣言するとAしますa.h

#include <iostream>

template<bool b>
class A { 
public:
  void print(std::ostream& out);
};

そして、で印刷メソッドを定義しますa.cpp(との明示的なインスタレーションを使用しtruefalse

#include "a.h"

template<bool b>
void A<b>::print(std::ostream& out) {
  out << "A" << b;
}

template class A<true>;
template class A<false>;

のメインメインプログラムの例は次のmain.cppとおりです。

#include "a.h"

int main() {
  A<true> a;
  a.print(std::cout);
}

上記の小さなプロジェクトは問題なくコンパイルされます。

質問:メソッドの定義print(内a.cpp)の上に明示的なインスタンス化を配置すると、コードはコンパイルされなくなり、通常のundefined reference to A<true>::print(...)エラーが発生します。

#include "a.h"

template class A<true>;
template class A<false>;

template<bool b>
void A<b>::print(std::ostream& out) {
  out << "A" << b;
}

なぜそうなのですか?

編集:コンパイルするMakefile

main : main.o a.o
    g++ main.o a.o -o main

main.o : main.cpp
    g++ -c main.cpp

a.o : a.cpp 
    g++ -c a.cpp
4

2 に答える 2

9

これがなぜそうなのかについての自然な説明はないと思います。明らかに、明示的なインスタンス化の後にメンバー関数が提供されたとしても、コンパイラーはメンバー関数の定義を認識できます。これは、メンバー関数が同じファイルにあるためです。

ただし、これにはコンパイラは必要ありません。実際、標準では明示的に禁止されています。

(§14.7.2/9) クラス テンプレートの特殊化に名前を付ける明示的なインスタンス化定義は、クラス テンプレートの特殊化を明示的にインスタンス化し、インスタンス化の時点で定義されているメンバーのみの明示的なインスタンス化定義です。

その理由として、次のことが考えられます。

  • 翻訳単位の後半で、一部のメンバー関数に対していくつかの明確な明示的な特殊化が存在する可能性があります。これらのうちどれをインスタンス化するかについて明示的な規則を設けることは、プログラマーの利益のためにも意味があります。

  • テンプレートが暗黙的にインスタンス化される場合、インスタンス化のポイントより前に定義された特殊化のみが考慮されます。したがって、ルールは暗黙的インスタンス化と明示的インスタンス化で同じです。

于 2013-01-04T06:16:55.773 に答える
1
template class A<true>;
template class A<false>;

テンプレートコードがヘッダー自体で定義されていることが通常期待されるのと同じ理由です。明示的なインスタンス化を実行するには、ユーザー (コンパイラー) がテンプレート クラスの定義全体を表示main.cppできる必要がありますが、 .

ただしa.cpp、クラスのすべての定義 (ここでは print メソッド) にアクセスできるため、明示的なインスタンス化がそこで機能します。

于 2013-01-04T06:06:39.750 に答える