4

次のコード例を考えると

struct S;

template<typename>
class C
{
public:
   void f(bool b)
   {
      if (b)
        g();
   }

   void g()
   {
     S{};
   }
};

int main()
{
   C<int>{}.f(false);
}

GCC は以下を正しく報告します。

example.cpp: In instantiation of 'void C< <template-parameter-1-1> >::g() [with <template-parameter-1-1> = int]':
10 : required from 'void C< <template-parameter-1-1> >::f(bool) [with <template-parameter-1-1> = int]'
21 : required from here
15 : error: invalid use of incomplete type 'struct S'

私の質問は次のとおりです。この保証された動作は、標準またはその他のドキュメントで何らかの決定を下していますか?

私の質問についてより正確に言うと:

Cはテンプレート クラスであり、メンバーf()g()参照されている場合にのみインスタンス化されます。f()で参照されていmain()ます。参照しない場合g()(内部的に不完全な型を使用しようとします)、コードはコンパイルされます。しかしg()、内部の if-branch 内で参照されていますf()。このブランチは決定論的に実行されることはありません。そのため、コンパイラはこのデッド コード ブランチを無視/削除する可能性があり、インスタンス化を回避できますg()(これにより、不完全な型を使用しようとするエラーが発生します)。ただし、これは発生していません (少なくとも私が試したコンパイラでは)。

これを許可すると、コンパイラの最適化設定を調整するだけで違法なコードが合法的なコードに変わることを理解していますが、それでも私の質問は、このコード例がいくつかのルール (最適化とテンプレート パスの順序など) によって失敗することが保証されているかどうかです。どこかで読めます。

洞察をありがとう。

4

2 に答える 2

3

インライン化とデッド コードの削除の最適化により、テンプレートのインスタンス化を防ぐことができますか?

いいえ。

デッド コードの削除は、オプティマイザのルールに従って「使用」されていないコードを削除するために実行できる最適化です。このような最適化は、実装が完全に準拠したままであることを望む限り、「as-if」ルールに違反しない場合があります。

とにかく、このプログラムは形式が正しくありません。のインスタンス化は、...C<int>内で見つかった呼び出しによって完全に必要とされmainますが、それは不可能です。このインスタンス化が成功した場合、その未使用部分は最適化されている可能性がありますが、それは「後の」ステップです。そもそも物理的に「存在する」ことができたプログラムの未使用部分のみを削除できます。

とにかく問題のあるコードを後で削除する可能性がある場合、そのような不正な形式のプログラムのコンパイルを防ぐために実装が必要かどうかを尋ねるのは興味深いかもしれません。これには、標準の「不正な形式」を定義する箇所を引用することで簡単に答えることができます。しかし、それは別の問題であり、私の意見では、バイザバイです。

ご興味があれば、一般的なケースでこの質問に肯定的に回答することはできません. ただし、そのフレーズが存在しない場合は、診断必要です。(私をそこに縛り付けないでください。)

于 2016-08-04T22:50:30.497 に答える