3
votes

I am writing a C++/CLI wrapper of a C++ Native Static Library.

I don't have much experience with either C++/CLI or C++. I have followed best practices I read on internet for the creation of C++/CLI wrappers. My wrapper has a pointer to the C++ class. And my C++ has the operator == overloaded.

I am trying to overload it also in my wrapper and use the implementation of the C++ class, but I am getting errors when the wrapper is null.

I searched how to know if my handle is null, and I found that you have to compare it with nullptr.

I have this method in C++/CLI

       MyOtherClass const* MyClass::MyMethod(MyWrapper^ instance)   
    {
        if(instance == nullptr)
        {
           return NULL;
        }

        return instance->Property;      
    }

The line if(instance == nullptr) calls my overloaded implementation of the == operator.

      static bool operator==(MyWrapper^ a, MyWrapper^ b)
    {
        return a->InternalInstance == b->InternalInstance; //Here System.AccessViolationException Exception
    }

The problem is that if a is null, this will throw an System.AccessViolationException exception.

And I cant just simply add a comparison with nullptr for a and b, because It creates a stack overflow.

static bool operator==(MyWrapper^ a, MyWrapper^ b)
{
    if(a == nullptr && b == nullptr) //Stack Overflow here because a == nullptr calls this method again.
        return true;
    if((a == nullptr && b != nullptr) || (a != nullptr && b == nullptr))
        return false;
    return a->InternalInstance == b->InternalInstance;
}

How can I override the == operator to use my C++ Native implementation, and still be protected of my handle being null?

2
You could have an explicit overloaded bool() operator that returns true if MyWrapper ^ is not a null ptr - yizzlez
if (a && b && a->InternalInstance == b->InternalInstance) should do it. If either a or b is NULL, it would evaluate to false, so the other conditionals would never get executed. - Zac Howland
@ZacHowland I tried with return a && b && a->internalUnit == b->internalUnit;, but that doesn't work, it throws object reference. I think this happens because when I debug the handle is "undefined". I guess this is not similar to what C++ would do. - Dzyann
@Dzyann That may be something specific to the CLI, but if the pointer is NULL or nullptr, it should equate to false if you had a statement if (a). The other option is to use ReferenceEquals. - Zac Howland
@ZacHowland you are right, that is what I expected, and that is why I tested out your code, I wanted to know what was going to actually do, for example would it call a == NULL internally when you do "a &&.."?. Well I don't know what it does, but in C++/CLI your suggestion sadly doesn't work. I even tried setting a = nullptr the line before the return to see if it was related with the fact that I didn't initialize a, but it fails anyway. - Dzyann

2 Answers

7
votes

Use Object::ReferenceEquals to explicitly check for null.

static bool operator==(MyWrapper^ a, MyWrapper^ b)
{
    if(Object::ReferenceEquals(a, nullptr) && Object::ReferenceEquals(b, nullptr))
        return true;

    if(Object::ReferenceEquals(a, nullptr) || Object::ReferenceEquals(b, nullptr))
        return false;

    return a->InternalInstance == b->InternalInstance;
}
2
votes

The problem here is that the overloaded function o == operate is performed on a reference type in C++/CLI, so if we follow the same way to do this in the native C++, it means that overloaded function of == operator is performed on a pointer type. But in native C++, we usually define == operator like this:

bool operator==(const X& lhs, const X& rhs){ /* do actual comparison */ }

Or think this way, if you overload the == for the pointer type in native C++, how can you compare this class pointer with null?

In the managed world, By default, the operator == tests for reference equality by determining if two references indicate the same object, so reference types do not need to implement operator == in order to gain this functionality. So you should implement the Equals function instead of overloading ==

Please refer this: Guidelines for Overloading Equals() and Operator == . Though it is about C#, I think it is apply the managed types in C++/CLI too.