次のコードを取ります。
class Foo
{
Foo const& operator =(Foo const& rhs); // disallow
};
struct Bar
{
public:
Foo foo;
template <class T>
T const& operator =(T const& rhs) { return rhs; }
};
struct Baz : public Bar {
using Bar::operator =;
};
int main()
{
Baz b1, b2;
b1 = b2;
}
プライベートであるFoo::operator =を使用しようとする、Bar :: operator =の自動生成された代入演算子が使用されるため、これはコンパイルに失敗します。これで結構です。そこで、Barにメンバーを追加しました。
Bar const& operator =(Bar const& b) { return Bar::operator=<Bar>(b); }
今、私たちは別の問題を抱えています。2つのオーバーロードがあり、そのうちの1つだけを使用できます。私はBazconst&を渡します。私がC++について知っていることはすべて、一致する非テンプレートが最初に選択されるため、これは非テンプレートバージョンを使用することになるはずであることを示唆しています。これもgccが行っていることのようです。Visual Studioは同意しないようです:
error C2666: 'Bar::operator =' : 2 overloads have similar conversions
could be 'const Bar &Bar::operator =(const Bar &)'
or 'const T &Bar::operator =<Baz>(const T &)'
with
[
T=Baz
]
while trying to match the argument list '(Baz, Baz)'
ここでgccを信じたくなります。これは、C ++を理解していることがこれを裏付けていることと、Visual Studioと一致しない場合は一般的にgccを支持しているためですが、これについてはそれほど心配していません。
私の非最小の例では、正直なところ、デフォルトで生成された代入演算子はまったく必要ありません。テンプレート演算子が作業を行うことに満足しています。正しく実行されます。ただし、VSはテンプレートと自動生成された代入演算子の競合について不平を言っているため、実際にはそのテンプレートをまったく機能させることができません。私は次のすべてを試しました:
- 代入演算子をプライベートで実装されていないものにする(「すべてのオーバーロードが有効であるとは限らない」ため、機能しません)
- それを作成する(上記のエラーにつながる)
- 除外します(デフォルトで生成された代入演算子で上記のエラーが発生します)
- そのタイプのテンプレートの特殊化を作成し、デフォルトの代入演算子を正確に一致させます(コンパイラーによると明示的に違法です)
誰かが私がこの問題を回避する方法について何か明るい考えを持っていますか?残念ながら、私のバージョンのVSは、自動生成された代入演算子のC ++ 0x「削除」オーバーライドをサポートしていないため、これはオプションではなく、このエラーを回避する他の方法を考えることはできません。