请使用以下代码:
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&amp ;.我所知道的关于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“delete”覆盖,所以这不是一个选项,我想不出任何其他方法来解决这个错误。
答案 0 :(得分:2)
在两个版本的赋值运算符之间进行解析时出现的歧义是由Baz定义中的“using Bar :: operator =”引起的。
无论是在Bar中隐式还是显式定义,非模板版本都采用参数“const Bar&amp;”,它与“Baz”不完全匹配,正如明确解析与模板所需的那样。
有很多方法,但真正的解决方案将取决于真正的来源。
要修复这个例子,我会做这些事情:
o防止const Bar& operator =(const Bar& b)
的自动生成,因为它将使用Foo的赋值运算符。您已尝试添加到Bar的定义中的内容将起作用:
Bar const& operator =(Bar const& b) {
return Bar::operator=<Bar>(b);
}
Baz定义中的using Bar::operator =
需要去。用包裹Bar :: operator =的函数替换它。如:
template <class T>
const T& operator =(const T& rhs) {
return Bar::operator =(rhs);
}
(当然,非时髦的代码总会返回* this - 一个Bar&amp;而不是参数的类型。)