8


3

クラスの内部と外部で定義されたテンプレートクラスのメンバー関数の違い

クラス宣言の内部と外部のテンプレートクラスのメンバー関数の定義に違いはありますか?

内部で定義:

template
class A
{
public:
    void method()
    {
        //...
    }
};

外部で定義:

template
class B
{
public:
    void method();
};

template
void B::method()
{
    //...
}

非テンプレートクラスの場合、これはインラインメソッドと非インラインメソッドの違いです。 これはテンプレートクラスにも当てはまりますか?

ほとんどの同僚のデフォルトは、クラス内で定義を提供することですが、私は常にクラス外の定義を優先しています。 私の好みは正当化されますか?

編集:上記のコードはすべて、クラスのヘッダーファイルで提供されると想定してください。

3 Answer


2


はい、テンプレートクラスについてもまったく同じことが言えます。

通常、テンプレートクラスのメソッド定義がインラインであることが望ましい理由は、テンプレートを使用すると、テンプレートがインスタンス化されるときに定義全体が表示される必要があるためです。

そのため、別の.cppファイルに関数定義を配置すると、リンカーエラーが発生します。 唯一の一般的な解決策は、クラス内または外部で「inline」キーワードで定義することにより、関数をインラインにすることです。 ただし、どちらの場合でも、関数が呼び出される場所であればどこでも表示できる必要があります。つまり、通常はクラス定義と同じヘッダーにある必要があります。


1


さらに入力する必要があることを除けば、違いはありません。 これには、「テンプレート」ビット、「インライン」、およびクラスを参照する際により多くの「精巧な」名前を使用する必要があることが含まれます。 例えば

template  class A {
  A method(A a) {
    // whatever
  }
};

template  inline A A::method(A a) {
  // whatever
}

メソッドが内部で定義されている場合、 A`を参照するときにテンプレートパラメーターリスト を常に省略して、 A`を使用できることに注意してください。 外部で定義するときは、戻り値の型とメソッドの名前で「フル」名を使用する必要があります(ただし、パラメーターリストでは使用しません)。


0


私はこれを知っています。

defining a member function outside of its template

次のようなテンプレートクラスのメンバー関数の定義を提供することはできません。

 // This might be in a header file:
 template
 class xyz {
    void foo();
  };
 // This might be later on in the header file:
  void xyz::foo() {
// generic definition of foo()
   }

これはいくつかの理由で間違っています。 これも:

      void xyz::foo() {
         // generic definition of foo()
      }

適切な定義には、テンプレートキーワードと、クラステンプレートの定義が宣言されたのと同じテンプレート引数が必要です。 そのため、次のようになります。

       template
          void xyz::foo() {
           // generic definition of foo()
                 }

メンバーテンプレートなど、他のタイプのテンプレートディレクティブがあり、それぞれが独自の形式をとることに注意してください。 重要なのは、あなたが持っているものを知ることですので、それぞれのフレーバーを書く方法を知っています。 一部のコンパイラのエラーメッセージでは何が間違っているのかが明確でない可能性があるため、これは特に重要です。 そしてもちろん、最新の良い本を入手してください。

テンプレート内にネストされたメンバーテンプレートがある場合:

    template
      struct xyz {
      // ...
      template
       struct abc;
        // ...
       };

xyzの外でabcをどのように定義しますか? これは動作しません:

     template
    struct xyz::abc { // Nope
      // ...
  };

これもしない:

 template
 struct xyz::abc { // Nope
// ...
 };

あなたはこれをしなければならないでしょう:

     template
       template
           struct xyz::abc {
            // ...
           };

abcは「プライマリ」テンプレートであるため、「…​ abc」ではなく「…​ abc」であることに注意してください。 IOWs、これは良くありません: