This was very, very weird. I spent quite a bit of time debugging and I could not find the problem either. In the end, I side-stepped it and got something to work. I did that by adding this method :
bool IsValid( size_t index ) { return ( index < m_iCount ); }
and then I adjusted two operators to look like this :
template< typename T >
T& Array< T >::operator[]( size_t index )
{
if( ! IsValid( index ) )
throw std::out_of_range("Invalid Index");
return m_pData[ index ];
}
template< typename T >
const T& Array< T >::operator[]( size_t index ) const
{
if( ! IsValid( index ) )
throw std::out_of_range("Invalid Index");
return m_pData[ index ];
}
and this works as expected - no exceptions are thrown.
I had to hack the code a bit to make it compile with VisualStudio 2022. It complained about the
iterator
class and its implementation. I folded all of that into the
Array
class and made it all inline and then things compiled and ran. However, there is still a problem with the
-=
operator's implementation so the test code you have commented out will not compile. I didn't figure that out. I see that it uses
std::remove
and
distance
so that probably needs to be revisted. Anyway, here are what my revisions look like :
template< typename T >
class Array
{
size_t m_iSize = 1000;
size_t m_iCount = 0;
T * m_pData = nullptr;
public:
Array() = default;
explicit Array( size_t iSize );
Array( const Array & Obj );
Array( Array && obj ) noexcept;
~Array() { delete m_pData; }
Array & operator = ( const Array& Obj );
Array & operator = ( Array&& obj ) noexcept;
Array operator + ( const Array &obj );
Array operator - ( const Array &obj );
Array operator += ( const Array &obj );
Array operator -= ( const Array &obj );
T & operator[]( size_t Index );
const T& operator[]( size_t Index ) const;
void Add( const T& Data );
void Add( T && Data );
size_t GetSize() const noexcept { return m_iCount; }
void swap( Array &obj ) noexcept;
friend void swap( Array& obj1, Array& obj2 );
bool IsValid( size_t index ) { return ( index < m_iCount ); }
template< typename T >
class iterator
{
size_t m_iCurrent;
explicit iterator( size_t iCount ) { m_iCount = iCount; }
public:
iterator() { m_iCurrent = -1; }
iterator( const iterator & obj ) : m_iCount( obj.m_iCount ) {}
iterator operator = ( const iterator& obj ) { m_iCount = obj.m_iCount; return *this; }
bool operator == ( const iterator& obj ) { return ( m_iCount == obj.m_iCount ); }
bool operator != ( const iterator& obj ) { return ! ( *this == obj ); }
iterator operator + ( const iterator& obj ) { return Array< T >::iterator{ m_iCount + obj.m_iCount }; }
iterator operator - (const iterator& obj) { return Array< T >::iterator{ m_iCount - obj.m_iCount }; }
iterator operator + ( size_t Index ) { m_iCurrent += Index; return *this; }
iterator operator - ( size_t Index ) { m_iCurrent -= Index; return *this; }
bool operator < ( const iterator& obj ) { return ( m_iCount < obj.m_iCount ); }
bool operator > ( const iterator& obj ) { return ! ( ( *this == obj ) || ( *this < obj ) ); }
T & operator[]( size_t Index )
{
if( Index >= m_iCount )
throw std::range_error("Invalid Index"); return m_pData[ Index ];
}
const T& operator[]( size_t Index ) const
{
if( Index >= m_iCount )
throw std::range_error( "Invalid Index" );
return m_pData[ Index ];
}
T operator *()
{
if( m_iCurrent => m_iCount ) throw std::runtime_error( "Invalid Array location" );
return m_pData[ m_iCurrent ];
}
};
iterator< T > erase( iterator< T > p )
{
if( ( m_iCount - p.m_iCount ) <= 0 )
throw std::range_error{ "Ivalid Array location" };
m_iCount -= p.m_iCount;
Array< T >::iterator p{ m_iCount };
return *this;
}
iterator< T > erase( iterator< T > pStart, iterator< T > pStop )
{
if( ( m_iCount - ( pStop.m_iCount - pStart.m_iCount ) ) <= 0 )
throw std::range_error{ "Invalid Array location" };
m_iCount -= ( pStop.m_iCount - pStart.m_iCount );
Array< T >::iterator p{ m_iCount };
return *this;
}
iterator< T > begin() { Array<T>::iterator p{ 0 }; return p; }
iterator< T > end() { Array<T>::iterator p{ m_iCount }; return p; }
};