问题描述
我正在处理一些旧代码,以前的一位开发人员在其中创建了一个Guid(全局唯一IDentifier)类,该类使用Microsoft的GUID结构作为成员变量(下面的成员“ MS”)。为了便于在两者之间进行转换,在Guid.h中定义了以下两个转换/广播运算符:
/// Returns a GUID structure
operator GUID() const
{
return MS;
}
/// Returns a reference to a GUID structure
operator GUID&()
{
return MS;
}
错误C2593:'运算符='是不明确的C:\ Program Files(x86)\ Windows 套件\ 10 \ include \ 10.0.18362.0 \ shared \ guiddef.h(27):注意:可能是 '_GUID&_GUID :: operator = {_ GUID &&)'C:\ Program文件(x86)\ Windows 套件\ 10 \ include \ 10.0.18362.0 \ shared \ guiddef.h(27):注意:或
'_GUID&_GUID :: operator =(const _GUID&)'
我假设要么编译器变得更严格(自VS2013开始),要么微软使用第二个重载的GUID赋值运算符更新了其GUID定义。发生此错误的示例如下:
void GuidExample(Guid initial)
{
GUID myGUID = initial;
}
我的理解是,在分配过程中,编译器将尝试使用我们提供的两个转换运算符之一将Guid转换为GUID。但是,它不知道要使用哪个转换运算符,因此也不知道要使用哪个赋值运算符。
如果我注释掉这两个转换运算符中的任何一个,则不会出现任何编译器错误。通过引用返回将允许访问GUID MS,这是可以的,因为它仍然是公共成员。因此,如果必须对转换操作进行一个定义,则将使用参考版本。
但是我的问题是,有没有办法既保留两个定义又避免歧义?
更新:最小的可复制示例。这将在VS2013中构建,而不会在VS2019中构建,这表明我之前提到的“'operator ='是模糊的”错误。
#include <guiddef.h>
class Guid
{
public:
union
{
char Data[16];
GUID MS;
struct
{
int Q1;
int Q2;
};
};
Guid()
{
Q1 = 0;
Q2 = 0;
}
/// Returns a GUID structure
operator GUID() const
{
return MS;
}
/// Returns a reference to a GUID structure
operator GUID& ()
{
return MS;
}
};
GUID winGUID;
void testAssign(Guid myGuid)
{
winGUID = myGuid; //This causes ambiguity
GUID anotherWinGUID = myGuid; //This does not
}
int main()
{
Guid a;
testAssign(a);
return 0;
}
解决方法
该错误告诉您编译器无法在复制分配和移动分配之间进行选择。所以你是对的,赋值运算符现在有两个重载,它们只是通常的重载。
编译器可能更严格。从VS2015 Update 3开始,Visual C ++一直使用/permissive-
加强规则。
修复可能很简单:
/// Returns a GUID structure
operator GUID() const
{
return MS;
}
/// Returns a reference to a GUID structure
operator GUID&() & // << the trailing & is a reference-qualification.
{
return MS;
}
这里的想法是,您不希望对临时GUID&
对象的Guid
引用在调用operator GUID&()
之后可能甚至无法生存。