1

I am working with some legacy code, where one of the previous developers created a Guid (Global Unique IDentifier) class that used Microsoft’s GUID struct as a member variable (member "MS" below). To allow easy conversion between the two, the following two conversion/casting operators were defined in Guid.h:

/// Returns a GUID structure
operator GUID() const
{
    return MS;
}

/// Returns a reference to a GUID structure
operator GUID&()
{
    return MS;
}

On moving the codebase to a VS2019 build, I get the following compiler error:

error C2593: 'operator =' is ambiguous C:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\shared\guiddef.h(27): note: could be '_GUID &_GUID::operator =(_GUID &&)' C:\Program Files (x86)\Windows Kits\10\include\10.0.18362.0\shared\guiddef.h(27): note: or
'_GUID &_GUID::operator =(const _GUID &)'

I’m assuming either the compiler has become more strict (since VS2013) or Microsoft updated their GUID definition with a second overloaded GUID assignment operator. An example of where this error is hit is as follows:

void GuidExample(Guid initial)
{
    GUID myGUID = initial;
}

My understanding is that during the assignment, the compiler will try to convert the Guid to a GUID using one of the two conversion operators we’ve supplied. However, it doesn’t know which one of our conversion operators to use, and therefore doesn’t know which assignment operator to use.

If I comment out either of the two conversion operators, I don’t get any compiler errors. Return by reference will allow access to GUID MS, which is OK because it is a public member anyway. So If I have to go with one definition of the conversion operation, I will go with the reference version.

However my question is, is there a way to keep both definitions and avoid the ambiguity?

UPDATE: Minimum reproducible example. This will build in VS2013 and will not in VS2019, showing the "'operator =' is ambiguous" error I noted earlier.

#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;
}
9
  • 1
    Why do you need both coversions? Converting to a non-const reference is a little odd Commented Aug 27, 2020 at 10:16
  • It complains about operator =. Is any defined? Commented Aug 27, 2020 at 10:16
  • 1
    This issue reminds me of the of the restriction on member function qualifiers: For a given function you can have both const and non-const, or &, &&, const & and const && - but not both. This is because having both will be ambiguous, and redundant. Commented Aug 27, 2020 at 10:32
  • @AlanBirtles it does seem odd and I'm going through the many use cases. For now I'm assuming it was done for a good reason. Commented Aug 27, 2020 at 10:46
  • @vahancho Yes, the two definitions are listed in the compiler output I posted. Commented Aug 27, 2020 at 10:48

1 Answer 1

2

The error tells you that the compiler cannot choose between copy-assignment and move-assignment. So you're right, there are now two overloads of the assignment operator, and they're just the usual ones.

The compiler might be more strict. Visual C++ has been tightening the rules with /permissive-, starting with VS2015 Update 3.

The fix is probably straightforward:

/// 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;
}

The idea here is that you don't want a GUID& reference to a temporary Guid object which might not even survive after the call to operator GUID&().

Sign up to request clarification or add additional context in comments.

4 Comments

Have given this a try and the compiler is still unhappy unfortunately, same output as my original post.
@Nimo Could you build a minimum reproducible example please. Here is a thing I started to try to understand your issue.
@nop666 will let you know. I appreciate the effort.
@nop666 just an update. I've made a basic example that DOES compile, although wasn't supposed to. So now need to track down the difference between the two.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.