質問

実際のデータ型と複雑なデータ型を定義する2つのラッパークラスに取り組んでいます。各クラスは、オーバーロードされたコンストラクターと、4つの算術演算子+、-、*、/、および5つの代入演算子=、+ =などを定義します。コードの繰り返しを避けるために、左右演算子の-hand-side引数は異なるデータ型です:

// real.h
class Real {
public:
  explicit Real(const double& argument) {...}
  explicit Real(int argument) {...}
  ...

  friend const operator*(const Real&; const Real&);
  template <class T> friend const Real operator*(const Real&, const T&);
  template <class T> friend const Real operator*(const T&, cont Real&);
  // Here, T is meant to be a template parameter for double and int

  // Repeat for all other arithmetic and assignment operators
};

// complex.h
class Complex {
public:
  explicit Complex(const Real& realPart) {...}
  explicit Complex(const Real& realPart, const Real& imaginaryPart) {...}
  // Overload for double and int data types
  ...

  friend const operator*(const Complex&, const Complex&);
  template <class T> friend const Complex operator*(const Complex&, const T&);
  template <class T> friend const Complex operator*(const T&, cont Complex&);
  // Here, T is is a template parameter for Real, double and int

  ...
};

ここでの問題は、次のようなコードです:

//main.cpp
void main() {
  Complex ac(2.0, 3.0);
  Real br(2.0);
  Complex cc = ac * br;
}

コンパイラ( gcc )エラー 'ac * br'の 'operator *'の曖昧なオーバーロードを返します。 >

  • template <class T> friend const Complex operator*(const Complex&, const T&) [with T = Real]
  • template <class T> friend const Real operator*(const T&, cont Real&) [with T = Complex]

クラスRealのテンプレートoperator *定義でTをComplexにできないことを指定する方法はありますか?または、テンプレートなしで実行し、引数データ型のあらゆる可能な組み合わせに対して各演算子を定義する必要がありますか?または、コードを再設計する方法はありますか?

役に立ちましたか?

解決

ああ、演算子の問題...

Boostは素敵なライブラリを作成したため、最小限のロジックを提供することで、他のすべてのバリエーションが自動的に追加されます。

Boost.Operators をご覧ください。 !

今、あなたが気づいたように、実際の問題については、汎用テンプレートを使用するのではなく、両方の種類の演算子(intおよびdouble)を定義する必要があります。これらの演算子に多くのロジックがある場合(これは疑わしい)、それらに常に共通の(テンプレート化された)メソッドを呼び出させることができます。

template <typename T>
Complex complex_mult_impl(T const& lhs, Complex const& rhs) { ... } // Note (1)

// return type is not 'Complex const', see (2)
Complex operator*(int lhs, Complex const& rhs)
{ 
  return complex_mult_impl(lhs,rhs);
}

ただし、Boost.operatorsを使用する場合は、Complex :: operator * =(int)およびComplex :: operator * =(double)のみを指定すると、スタンドアロンバージョンが自動的に推測されます:)

(1)すべての引数が組み込みの場合、ここで値渡しを使用できます。 Boost.CallTraits を検討することもできます。引数が組み込みであるかどうかに応じて、値による参照と参照による選択を自動的に選択します。テンプレートに便利です。

(2)値で引数を返す場合、引数をconstとして修飾するのは無意味です。 Complexキーワードは参照とポインタの意味を意味するだけです。ここでは、ユーザーが「単純な」<=> ...をインスタンス化することを妨げるものは何もありません。

他のヒント

RealクラスまたはComplexクラスに非グローバル乗算演算子を含めることができます。

class Real 
{
  ........

  template <class T> const Real operator*(const T&);
  const Real operator*(const Real&);

};

Complexコンストラクターを明示的にできますか? これは、RealからComplexへの暗黙的な変換が許可されないことを意味し、演算子*

を明確にする必要があります。
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top