6

私は最近、私を不安にさせているテンプレートを専門化しているときに状況に遭遇しました:

foo.h:

template <class T>
void foo() {
  std::cout << "This is the generic foo" << std::endl;
}

foo.cc:

#include "foo.h"
template <>
void foo<int>() {
  std::cout << "This is foo<int>" << std::endl;
}

main.cc:

#include "foo.h"

int main() {
  foo<int>();
}

それで。私は次のようにコンパイルします:

g++ -c main.cc
g++ -c foo.cc
g++ -o main main.o foo.o

出力は"This is foo<int>"です。私はこの出力が好きです。しかし、私が観察しているものがgccに固有のものである可能性があるのではないかと心配しています(他のコンパイラーにアクセスできないため、確認できません)。

gccが行っていることは次のとおりです。main.ccをコンパイルすると、foo.ccの特殊化を認識していないため、foo呼び出しのジェネリックコードが出力されると思います。ただし、foo.oとリンクすると、同じ署名を持つため、代わりに特殊化が使用されます。

しかし、これは頼りになるのは悪いことですか?他のコンパイラ(またはgccの異なるバージョンでも?)がテンプレートコードを出力するときに署名を壊してしまう可能性があるのではないかと心配しています。foo.oとのリンクでは、私が望むような一般的なアクションが置き換えられません。これは有効な心配ですか?私は不安を感じることをたくさん読みましたが、私の現在の状況で何が起こっているのかについて自信を持って感じるものは何もありません。

4

1 に答える 1

8

私が観察しているものがgccに固有のものである可能性があるのではないかと心配しています(他のコンパイラーにアクセスできないため、確認できません)。

心配するのには十分な理由があります。プログラムの形式が正しくなく、コンパイラが通知する必要さえありません。

C ++11規格のパラグラフ14.7.3/6は、次のように規定しています。

テンプレート、メンバーテンプレート、またはクラステンプレートのメンバーが明示的に特殊化されている場合、その特殊化は、その特殊化が最初に使用される前に宣言される必要があります。これにより、そのような使用が発生するすべての翻訳ユニットで、暗黙的なインスタンス化が行われます。 ; 診断は必要ありません。プログラムが明示的な特殊化の定義を提供せず、特殊化が暗黙的なインスタンス化を実行する方法で使用されているか、メンバーが仮想メンバー関数である場合、プログラムは不正な形式であり、診断は必要ありません。宣言されているが定義されていない明示的な特殊化に対して、暗黙的なインスタンス化が生成されることはありません

プログラムが一貫した動作をするためには、インスタンス化の時点からスペシャライゼーションが表示されている必要があります。あなたの場合、そうではありません:あなたは他の翻訳ユニットに含まれていないファイルにそれを委任しています。

パラグラフ14.7.3/7標準は、これを怠った場合に何が起こるかについて非常に明確です。

関数テンプレート、クラステンプレート、クラステンプレートのメンバー関数、[...]の明示的な特殊化宣言の配置は、明示的な特殊化宣言の相対的な位置付けとそのインスタンス化のポイントに従って、プログラムが整形式であるかどうかに影響を与える可能性があります。上および下で指定された変換単位。スペシャライゼーションを作成するときは、その場所に注意してください。またはそれをコンパイルさせることは、その焼身自殺を燃やすような試みになるでしょう。

私は最後の文がそれを明らかにしていると思います。

ここで行うべきことは、プライマリテンプレートの暗黙的なインスタンス化が発生する前に、関数テンプレートの明示的な特殊化を導入する意図を宣言することです。これを行うには、次のようにします。

foo.h

template <class T>
void foo() {
   std::cout << "This is the generic foo" << std::endl;
}

template <> void foo<int>(); // Introduce a declaration of your
                             // explicit specialization right
                             // after you defined the primary
                             // template!

プライマリテンプレートの定義の直後に宣言を導入することにより、プライマリテンプレートが表示されている場所に、その完全な特殊化が存在することがわかり、焼身自殺からあなたを救うことができます。

于 2013-02-28T00:40:11.993 に答える