1. ホーム
  2. c++

[解決済み] クラステンプレートでの演算子のオーバーロード

2022-02-28 06:03:54

質問

テンプレート・クラスの演算子オーバーロードの定義に問題があります。この仮想的なクラスを例にとってみましょう。

template <class T>
class MyClass {
  // ...
};

  • operator+=

    // In MyClass.h
    MyClass<T>& operator+=(const MyClass<T>& classObj);
    
    
    // In MyClass.cpp
    template <class T>
    MyClass<T>& MyClass<T>::operator+=(const MyClass<T>& classObj) {
      // ...
      return *this;
    }
    
    

    このコンパイラーエラーが発生します。

    no match for 'operator+=' in 'classObj2 += classObj1'
    
    
  • 演算子<<

    // In MyClass.h
    friend std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj);
    
    
    // In MyClass.cpp
    template <class T>
    std::ostream& operator<<(std::ostream& out, const MyClass<T>& classObj) {
        // ...
        return out;
    }
    
    

    このコンパイラの警告が表示されます。

    friend declaration 'std::ostream& operator<<(std::ostream&, const MyClass<T>&)' declares a non-template function
    
    

何が間違っているのでしょうか?

どうすればいいですか?

// In MyClass.h
MyClass<T>& operator+=(const MyClass<T>& classObj);


// In MyClass.cpp
template <class T>
MyClass<T>& MyClass<T>::operator+=(const MyClass<T>& classObj) {
  // ...
  return *this;
}

テンプレートでは無効です。演算子の完全なソースコードは、それが使用されるすべての翻訳ユニットに含まれていなければなりません。これは通常、コードがヘッダーの中にインラインで存在することを意味します。

編集:技術的には、標準によれば、テンプレートのエクスポートは可能ですが、サポートしているコンパイラはごくわずかです。また、MyClass.cppでT-であるすべての型に対して明示的にテンプレートをインスタンス化すれば、上記のようなことも可能ですが、現実には、それはテンプレートの意味を無視することになります。

もっと編集する:あなたのコードを読みましたが、例えばoperator[]のオーバーロードなど、いくつかの作業が必要です。さらに、典型的には、私は次元をテンプレートパラメータの一部にし、コンパイル時に+または+=の失敗を捕らえることを可能にし、型を意味のあるスタックアロケートすることを可能にします。例外クラスもstd::exceptionから派生させる必要があります。しかし、これらはいずれもコンパイル時のエラーには関係なく、単に素晴らしいコードではありません。