The address operator(&) overload breaks basic expectation from SafeInt<T,E> class


I posted this question on a forum in MSDN [Prev question] (https://social.msdn.microsoft.com/Forums/vstudio/en-US/751fd20b-896e-494c-953e-a618b8cf5247/why-was-the-address-operator-overloaded-in-safeint-class?forum=vcgeneral#b28efc1c-8ce2-4ddf-b8cf-4a0773c064bb). It was wrongly worded and I didn't get a satisfactory response.

I am reporting this as a bug. Let me know if this isn't a bug.

I have a huge code base which I am migrating to use SafeInt<T,E>. The integer types in my code have been typedef'd to userdefined types for ease of modification of types.

For ex: situations like moving to SafeInt<T,E>. My issue pertains to the fact that &(address operator) has been overloaded to return T* instead of SafeInt<T, E> * .

Consider the following snippet.
#include "SomeHeaderWithTypedefs.h"
//other headers...

void someFunction(MyInt* intPointerArgument); //Function signature I have.

int main()
   MyInt anIntVar = 10; 
//Contents of SomeHeaderWithTypedefs.h

//Old Typedef:
typedef int MyInt;

//New Typedef:
typedef SafeInt<int> MyInt;
Changing the above typedef to point to SafeInt should not break my code where I send address of "MyInt" to the function.

It breaks because the &(address operator) has been overloaded to return T* for "ease of use". This breaks basic functionality and should not be so.

A Workaround
To fix the above code I have to change everyplace I try to use the address of MyInt to the following
I hope this is a convincing argument to categorize this functionality as a bug.



dcleblanc wrote Dec 1, 2016 at 11:43 PM

I apologize for the very long delay in answering. This was something that I went back and forth on - from the code:
// Or if SafeInt< T, E >::Ptr() is inconvenient, use the overload
// operator &
// This allows you to do unsafe things!
// It is meant to allow you to more easily
// pass a SafeInt into things like ReadFile
T* operator &() SAFEINT_NOTHROW { return &m_int; }
const T* operator &() const SAFEINT_NOTHROW { return &m_int; }
It seemed like a much more common problem that we would have this:

int x = fcn();

... lots of code ...

If we suddenly pass it a SafeInt that it wasn't expecting, that breaks, too. It seemed unusual to want to pass around a SafeInt by pointer, and that if you really needed to pass a SafeInt, then it would be best done by reference - after all, this is C++.

The typedef gets you into some tricky places, which you have run into.

The reason for the existence of const T* Ptr() const SAFEINT_NOTHROW { return &m_int; } is that if you wanted to comment out:
T* operator &() SAFEINT_NOTHROW { return &m_int; }
const T* operator &() const SAFEINT_NOTHROW { return &m_int; }
then you could do so, use the nice helper functions where it now doesn't compile. I have an awful lot of conditional compilation based on whether some define is set. This hasn't been a common ask, and because the header is open source, I think maybe the best approach for you would be to comment out those two lines, and not complicate your code with lots of std::addressof declarations.

I might add this as a conditional compile just to bring it to the top as an option. I apologize that this has been inconvenient.