当前位置: 动力学知识库 > 问答 > 编程问答 >

c++ - Getting around the auto-generated assignment operator (VS bug?)

问题描述:

Take the following code:

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;

}

This fails to compile because the auto-generated assignment operator for Bar::operator = will be used, which attempts to use Foo::operator =, which is private. This is OK. So I added in an additional member to Bar:

Bar const& operator =(Bar const& b) { return Bar::operator=<Bar>(b); }

Now we have a different problem. I have two overloads, only one of which can be used. I'm passing in a Baz const&. Everything I know about C++ suggests that this should end up using the non-template version, because matching non-templates get chosen first. This also appears to be what gcc is doing. Visual Studio seems to disagree:

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)'

I'm tempted to believe gcc here, both because my understanding of C++ confirms this, and because I generally side with gcc when it disagrees with Visual Studio, but I'm not quite as concerned about that as I am about this:

In my non-minimal example, I honestly don't need that default-generated assignment operator at all. I would be more than happy with the template operator doing the work - it will do it correctly. However, because VS is complaining about the conflict between the template and the auto-generated assignment operator, I can't actually get that template to work at all. I've tried all of the following:

  1. Making the assignment operator private and unimplemented (doesn't work, because "not all overloads are acecssible")
  2. Creating it (leading to the error above)
  3. Leaving it out (leading to the error above with the default-generated assignment operator)
  4. Creating a specialization of the template for that type, thus matching the default assignment operator exactly (explicitly illegal according to the compiler)

Does anyone have any bright ideas on how I might get around this problem? Unfortunately my version of VS does not support the C++0x "delete" override of the autogenerated assignment operator, so that is not an option, and I can't think of any other ways of getting around this error.

网友答案:

The ambiguity seen when resolving between the two versions of the assignment operator is caused by the "using Bar::operator =" in the definition of Baz.

Whether implicit or explicitly defined in Bar, the non-template version takes the argument "const Bar&", which does not exactly match a "Baz", as required for unambiguous resolution vs. a template.

There are many ways around this, but the real solution will depend on the real source.

To fix the example, I would do these things:

o Prevent auto-generation of const Bar& operator =(const Bar& b) because it will use Foo's assignment operator. What you have already tried adding to Bar's definition will work:

Bar const& operator =(Bar const& b) {
    return Bar::operator=<Bar>(b); 
}

o using Bar::operator = in the definition of Baz needs to go. Replace it with a function that wraps Bar::operator=. Such as:

template <class T>
const T& operator =(const T& rhs) {
    return Bar::operator =(rhs); 
}

(Of course, non-funky code would always return *this -- a Bar&, rather than the argument's type.)

分享给朋友:
您可能感兴趣的文章:
随机阅读: