![](/img/trans.png)
[英]'boost::operator ==' : 4 overloads have similar conversions
[英]Assignment operator overloads have similar conversions (only in VS)
我有一个有三个类(A,B和C)的类层次结构。 A和B是基类,使用派生类型进行参数化。 C类来自A和B两者。
类B为类型A的对象提供赋值运算符,而类C using super::operator=
声明继承此赋值运算using super::operator=
。
当我从类型A的对象在类B中定义构造函数时,我得到错误: 两个重载在Visual Studio 2013中有类似的转换 (C2666),但我没有在gcc(4.8.2)中收到任何错误或警告,clang(3.4)和intel icc(Studio 2015)。 (用-Wall -pedantic
编译)
这里是简化的例子:
template <class Model> struct A {};
template <class Model> struct B
{
B() {}; // default constructor
// copy constructor for objects of type A
template <class M>
B(A<M> const&) {}
// assignment operator for objects of type A
template <class M>
Model& operator=(A<M> const& rhs)
{
return static_cast<Model&>(*this);
}
};
struct C : public B<C>, public A<C>
{
typedef B<C> super;
// copy assignment operator
C& operator=(C const& rhs) { return *this; }
// adopt assignment operator for A<C> from super-class
using super::operator=;
};
int main()
{
C c;
A<C> a;
c = a;
}
如果我用非模板化的类替换模板化的类A,它也可以在Visual Studio中编译而不会出错 - 但这不是它可以解决的方式。
我的问题是 :这个结构是否符合标准,或错误信息是否正确? B中的复制构造函数的explicit
说明符是否有助于解决问题?
顺便说一下:在Visual Studio中,我得到了警告 : 指定了多个赋值运算符 (C4522),因为C类中的复制赋值运算符。有人可以解雇我,为什么这应该是个问题?
GCC和CLANG是正确的,MSVC是错误的:
陈述c=a;
使用您在B
定义的operator=
,因为A<C>
不一定是C
所以让我们通过手动执行类型替换来记下operator=
of B<C>
的声明:
template <class M>
C& operator=(A<M> const& rhs)
由于a
是A<C>
,此模板的明显隐式实例化候选者将是:
C& operator=(A<C> const& rhs)
这实际上是唯一可能的实例化(您可以通过显示typeinfo来验证GCC是否使用它)。
如果您将C类简化为更简约的形式,您仍然会收到错误 :
struct C : public B<C> // single inheritance
{ using B<C>::operator=; }; // nothing else
实际上问题是由构造函数B(A<M> const&)
:
MSVC错误地识别出成员函数的隐式特化的第二个potental候选者。 由于此构造函数允许从A<M>
隐式转换为B<C>
,因此候选者是:
C& operator=(B<C> const& rhs)
但根据C ++标准,编译器根本不应该设想这个:
14.8.1 / 6: 如果参数类型不包含参与模板参数推导的模板参数 , 则将对函数参数执行隐式转换,以将其转换为相应函数参数的类型 。
所以这显然是MSVC的一个错误。
顺便说说:
关于多个assignemnt运营商的警告只是一个信息 。 显然,MS认为这可能是导致错误的常见原因。 现在到了核心问题......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.