1

operator+=メンバー関数としてoperator+実装され、非メンバー関数として実装されているボリュームオブジェクトのテンプレートクラスがあります。

template <typename Class>
Class operator+(Class c1, const Class& c2) {
   return c1 += c2;
}

// Add a constant to every element in the volume
template <typename Class, typename dataType>
Class operator+(Class c, dataType constant) {
   return c += constant;
}

template <typename Class, typename dataType>
Class operator+(dataType constant, Class c) {
   return c += constant;
}

それから私は以下をコンパイルしようとします:

volume + 1.3;

ここで、volumeは、テンプレート化されたボリュームクラスから派生したタイプです。これにより、次のエラーが発生します。

error: ambiguous overload for ‘operator+’ in ‘volume + 1.3’

呼び出しがあいまいなのはなぜですか?

4

3 に答える 3

4

2番目のテンプレートはとで推測できます。または3番目のテンプレートはとで推測できClass = typeof(volume)ます。3番目のテンプレートがインスタンス化に失敗する可能性が非常に高い場合でも、コンパイラーはそれらのいずれかを選択できません。dataType = doubledataType = typeof(volume)Class = double

私はそれvolumeがユーザー定義のタイプを持っていると仮定しています。組み込み型の場合、演算子のオーバーロード解決のみを目的として、テンプレートが考慮される前に選択される「実際の」関数などがあるため、呼び出しがあいまいになることはないと思います。double operator+(double, double);

于 2012-06-15T10:06:53.010 に答える
2

Volume がクラスの名前であるとします。

Volume volume;

ボリューム + 1.3 を解決する必要がある場合、コンパイラは適切なメソッドを探します。そして、それらのうちの2つを見つけます。

  1. テンプレート クラス operator+(クラス c、dataType 定数)
  2. テンプレート クラス operator+(dataType 定数、クラス c)

なんで?

これらの定義の文字通りの「クラス」には意味がありません。あなたが意図したとしても、「ボリューム」クラスとはまったく関係ありません。

したがって、コンパイラはそれを次のように認識します。

template <typename X, typename Y>
X operator+(X c, Y constant)
  1. テンプレート Z 演算子+(Z 定数, X c)

したがって、これらは両方とも、行のコンパイラーにとって同等に十分です

volume+1.3

すなわち:(1)から:

Volume operator+(Volume c, double constant)

(2) から :

Volume operator+(Volume constant, double c)

現在、コンパイラにとってはあいまいです。

解決策 : ボリューム タイプごとにこれらの演算子を個別に定義する必要があるという解決策しかわかりません。

于 2012-06-15T10:40:37.827 に答える
0

他の人は、あなたのコードが機能しない理由を説明しました。しかし、一般に、引数の型を受け入れる関数テンプレートを作成することは非常に悪い考えです。それはあいまいさを求めているだけです。

operator+ を使用したい「ボリューム」タイプのリストがある場合は、それらに共通の基本クラスを継承させることができます。これをテンプレートでパラメータ タイプとして使用できます。

template<typename T>
struct VolumeBase { 
  T copy() const { return get(); }
  T const& get() const { return static_cast<T const&>(*this); }
};

template <typename Class, typename Class>
Class operator+(VolumeBase<Class> const& c, VolumeBase<Class> const& c1) {
   return c.copy() += c1.get();
}

template <typename Class, typename dataType>
Class operator+(VolumeBase<Class> const& c, dataType constant) {
   return c.copy() += constant;
}

template <typename Class, typename dataType>
Class operator+(dataType constant, VolumeBase<Class> const& c) {
   return c.copy() += constant;
}

残念ながら、この方法で引数のコピーをテンプレートの本体に移動しましたが、インライン化できる場合 (このような単純な本体の場合は問題ないと思います)、パフォーマンスが低下することはありません。したがって、各ボリューム クラスは次のように定義されます。

class MyVolumeClass : public VolumeBase<MyVolumeClass> { ... };
于 2012-06-15T15:05:14.200 に答える