繁体   English   中英

多个转换运算符导致赋值运算符歧义

[英]Multiple conversion operators causing assignment operator ambiguity

我正在处理一些遗留代码,其中一位以前的开发人员创建了一个 Guid(全局唯一标识符)类,该类使用 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;
}

在将代码库移动到 VS2019 版本时,我收到以下编译器错误:

错误 C2593:'operator =' 不明确 C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\shared\\guiddef.h(27): 注意:可能是 '_GUID &_GUID::operator =( _GUID &&)' C:\\Program Files (x86)\\Windows Kits\\10\\include\\10.0.18362.0\\shared\\guiddef.h(27):注意:或
'_GUID &_GUID::operator =(const _GUID &)'

我假设编译器变得更加严格(自 VS2013 起),或者 Microsoft 使用第二个重载的 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&()后甚至可能无法生存。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM