5

次の例を考えてみましょう:

#include <iostream>

template< int a >
void foo();

int main(int argn, char* argv[])
{
    foo<1>();
}

template<>
void foo<1>()
{
    std::cout<<1<<std::endl;
}

コンパイルは失敗し、次のエラーメッセージが表示されます。

rg.cpp:12: error: specialization of ‘void foo() [with int a = 1]’ after instantiation

標準のどの段落がこのエラーを説明していますか?

PS:mainの前に関数定義を移動すると、エラーがなくなることを知っています。

4

1 に答える 1

10

これは、標準によると未定義の動作だと思います。UBの場合にツールチェーンで実行できることには制限がありません。コンパイラエラーを生成することは、よりフレンドリーな可能性の1つです。


セクション[temp.spec]、14.7p5は言う

与えられたテンプレートと与えられたテンプレート引数のセットに対して、

  • 明示的なインスタンス化の定義は、プログラムに最大1回表示されます。
  • 明示的な特殊化は、プログラム内で最大1回定義されるものとし(3.2による)、
  • 明示的なインスタンス化と明示的な特殊化の宣言の両方は、明示的なインスタンス化が明示的な特殊化の宣言に従わない限り、プログラムに表示されないものとします。

このルールの違反を診断するために実装は必要ありません。

セクション[temp.expl.spec]14.7.3p6は次のように述べています。

テンプレート、メンバーテンプレート、またはクラステンプレートのメンバーが明示的に特殊化されている場合、その特殊化は、その特殊化が最初に使用される前に宣言され、暗黙のインスタンス化が発生します。 ; 診断は必要ありません。


プログラムがこれらの要件に違反しています。

于 2011-05-06T14:19:52.320 に答える