采取以下代码:
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;
}
这无法编译,因为将使用自动生成的 Bar::operator = 赋值运算符,它尝试使用私有的 Foo::operator =。还行吧。所以我在 Bar 中添加了一个额外的成员:
Bar const& operator =(Bar const& b) { return Bar::operator=<Bar>(b); }
现在我们有一个不同的问题。我有两个重载,只能使用其中一个。我正在传递一个 Baz const&。我所知道的关于 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“删除”覆盖,所以这不是一个选项,我想不出任何其他方法来解决这个错误。