You're right, ~T() does work.
I think before I was doing: ptr[i]->~T();
Now it seems to work fine.
I beefed up the code to act like new if ptr is NULL, and act like delete if newSize is 0.
Code:
template <typename T>
T* Realloc( T* ptr,
size_t oldSize,
size_t newSize )
{
if ( oldSize == newSize )
{
return ptr;
}
HANDLE hHeap = GetProcessHeap();
T* pNew = NULL;
if ( ptr != NULL ) // If no memory yet, go straight to HeapAlloc().
{
// Try to expand array.
pNew = (T*)HeapReAlloc( hHeap,
HEAP_REALLOC_IN_PLACE_ONLY,
ptr,
(newSize * sizeof( T )) );
}
if ( pNew == NULL ) // Failed to expand array.
{
if ( newSize > 0 )
{
// Try to allocate new memory and copy old array to new one.
pNew = (T*)HeapAlloc( hHeap, 0, (newSize * sizeof( T )) );
if ( pNew == NULL ) // Not enough memory.
{
throw std::bad_alloc( "No memory!" );
}
}
// Copy all old values to new array and call each old elements destructor.
for ( size_t i = 0; i < oldSize; ++i )
{
if ( i < newSize ) // In case user wants to delete or shrink array.
{
new( &pNew[i] ) T( ptr[i] );
}
ptr[i].~T();
}
if ( ptr != NULL )
{
HeapFree( hHeap, 0, ptr ); // Release old memory.
}
}
// Fill the rest of the array with default T's.
for ( size_t i = oldSize; i < newSize; ++i )
{
new( &pNew[i] ) T();
}
return pNew;
}