I have an auto pointer implementation:
template <typename T, bool Arr = false>
class GAutoPtr
{
T *Ptr;
public:
typedef GAutoPtr<T, Arr> &AutoPtrRef;
GAutoPtr(T *ptr = 0)
{
Ptr = ptr;
}
GAutoPtr(AutoPtrRef p)
{
Ptr = p.Release();
}
~GAutoPtr() { Empty(); }
operator T*() { return Ptr; }
T *Get() { return Ptr; }
T *operator->() const { LgiAssert(Ptr); return Ptr; }
inline void Empty()
{
if (Arr)
delete [] Ptr;
else
delete Ptr;
Ptr = 0;
}
AutoPtrRef operator =(GAutoPtr<T> p)
{
Empty();
Ptr = p.Ptr;
p.Ptr = 0;
return *this;
}
void Reset(T *p)
{
if (p != Ptr)
{
Empty();
Ptr = p;
}
}
T *Release()
{
T *p = Ptr;
Ptr = 0;
return p;
}
};
typedef GAutoPtr<char, true> GAutoString;
typedef GAutoPtr<char16, true> GAutoWString;
And that works fine in Visual C++ 6. However in Visual C++ 2005 or 2008 I can't return an auto pointer from a function without things going horribly wrong.
e.g.
GAutoString Func()
{
char *s = new char[4];
strcpy(s, "asd");
return s;
}
int main()
{
GAutoString a = Func();
/// a.Ptr is now garbage
}
What happens is that the compiler creates a temporary GAutoString to hold the return value for the function, and then in passing that to the variable 'a' on the stack calles the operator T*() of the temp variable, and then the GAutoPtr(T *ptr = 0) constructor, instead of just using the copy constructor: GAutoPtr(AutoPtrRef p)
This results in the temp auto ptr deleting the memory and 'a' holding a pointer to the freed memory.
However in VC6 it DOES call the right constructor. Now in saying all this I also use gcc on Linux and Mac, so whatever code I write needs to work there too. VC2008 prevents you from using a non-const by value variable in the copy constructor. Also I don't want "const" anyway, because the copy constructor takes ownership of the memory block which removes ownership from the object being copied... thus modifying it.
How can I make this work in VC 2005/2008?