未使用のテンプレートクラスメソッドのオブジェクトコードは生成されますか?

StackOverflow https://stackoverflow.com/questions/183108

  •  06-07-2019
  •  | 
  •  

質問

3つの異なる型パラメーターでインスタンス化されるC ++テンプレートクラスがあります。これらのタイプのうち1つだけに対してクラスが必要とするメソッドがあり、他の2つのタイプでは呼び出されません。

そのメソッドのオブジェクトコードは3回生成されますか(テンプレートがインスタンス化されるすべてのタイプに対して)、またはオブジェクトコードは1回のみ生成されますか(実際に使用されるタイプに対して)?

役に立ちましたか?

解決

クラステンプレートがインスタンス化されると仮想メンバー関数がインスタンス化されますが、非仮想メンバー関数は呼び出された場合にのみインスタンス化されます。

これは、C ++標準の[temp.inst]で説明されています(C ++ 11では、これは§ 14.7.1 / 10です。C++ 14では、§ 14.7.1です。 / 11、C ++ 17では§ 17.7.1 / 9です。以下のC ++ 17からの抜粋)

  

実装は、関数テンプレート、変数テンプレート、メンバーを暗黙的にインスタンス化してはなりません   テンプレート、非仮想メンバー関数、メンバークラス、クラステンプレートの静的データメンバー、または    constexpr ifステートメント(9.4.1)のサブステートメント。ただし、このようなインスタンス化が必要な場合を除きます

また、特定のテンプレートパラメータに対して一部のメンバー関数がインスタンス化できない場合でも、クラステンプレートをインスタンス化することができることに注意してください。例:

template <class T>
class Xyzzy
{
public:
    void CallFoo() { t.foo(); }  // Invoke T::foo()
    void CallBar() { t.bar(); }  // Invoke T::bar()

private:
    T t;
};

class FooBar
{
public:
    void foo() { ... }
    void bar() { ... }
};

class BarOnly
{
public:
    void bar() { ... }
};

int main(int argc, const char** argv)
{
    Xyzzy<FooBar>  foobar;    // Xyzzy<FooBar> is instantiated
    Xyzzy<BarOnly> baronly;   // Xyzzy<BarOnly> is instantiated

    foobar.CallFoo();         // Calls FooBar::foo()
    foobar.CallBar();         // Calls FooBar::bar()

    baronly.CallBar();        // Calls BarOnly::bar()

    return 0;
}

BarOnly :: foo()などは存在しないため、Xyzzy :: CallFoo()はインスタンス化できませんが、これは有効です。この機能は、テンプレートメタプログラミングツールとしてよく使用されます。

ただし、「インスタンス化」は、テンプレートのサイズは、生成されるオブジェクトコードの量と直接相関しません。それはコンパイラ/リンカーの実装に依存します。

他のヒント

コンパイラと設定に依存すると思います。たとえば、MSVC6がすべてを生成したと思いますが、VS2005はそうではありません。仕様では、コンパイラーはすべきではありませんが、実際にはコンパイラーに依存します(たとえば、MSVC6のブーストには多くの回避策があります)。 / opt:refが有効な場合、リンカは参照されていない関数を削除できます(VSの場合、他のコンパイラに同等のオプションが存在します)。

通常、はい。

コンパイラが実際に知っているのは、プログラムが各クラスのインスタンスを少なくとも1つ作成できることです。しかし、それらのインスタンスをどうするかはわかりません。したがって、コードはほぼ確実に生成されます。

とはいえ、問題のメソッドが仮想ではなく、呼び出されない場合、リンカーは通常のデッドコード削除機能でそれらを削除できます。そのため、生成された(およびコンパイルされた)コードは最終的なEXEには含まれません。

また、これはすべてが同じではないため、使用されているC ++コンパイラに大きく依存します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top