////////////////////////////////////////////////////////////////////////////////
/** 
  \file
  \brief \ru Одномерный массив указателей.
         \en One-dimensional array of pointers. \~

*/
////////////////////////////////////////////////////////////////////////////////

#ifndef __TEMPL_RP_ARRAY_H
#define __TEMPL_RP_ARRAY_H

#include <system_cpp_standard.h>
#include <io_define.h>
#include <tool_quick_sort.h>
#include <templ_delete_define.h>
#include <string.h>
#include <tool_err_handling.h>



FORVARD_DECL_TEMPLATE_TYPENAME( class   RPArray );
FORVARD_DECL_TEMPLATE_TYPENAME( bool    set_Rarray_size( RPArray<Type> &, size_t newSize ) );
FORVARD_DECL_TEMPLATE_TYPENAME( size_t  find_in_array  ( const RPArray<Type> & arr, const Type * el ) );
FORVARD_DECL_TEMPLATE_TYPENAME( reader & CALL_DECLARATION operator >> ( reader & in, RPArray<Type> & ref ) );
FORVARD_DECL_TEMPLATE_TYPENAME( writer & CALL_DECLARATION operator << ( writer & out, const RPArray<Type> & ref ) );
FORVARD_DECL_TEMPLATE_TYPENAME( reader & CALL_DECLARATION operator >> ( reader & in, RPArray<Type> *& ptr ) );
FORVARD_DECL_TEMPLATE_TYPENAME( writer & CALL_DECLARATION operator << ( writer & out, const RPArray<Type> * ptr ) );


//------------------------------------------------------------------------------
/** \brief \ru Одномерный массив указателей на объекты.
           \en One-dimensional array of pointers to objects. \~
  \details \ru Шаблонный массив, работающий с указателями на объекты. \n
           \en A template array working with pointers to objects. \n \~
  \ingroup Base_Tools_Containers
*/
// ---
template <class Type>
class RPArray {
public:
  /// \ru Имя указателя на объект. \en A name of the pointer to the object. 
  typedef Type * TPtr; 
  typedef Type * value_type;
  typedef Type * const & const_reference;
  typedef Type *       & reference;  

protected:
  size_t  count; ///< \ru Количество элементов в массиве. \en The number of elements in array. 
  size_t  upper; ///< \ru Под какое количество элементов выделена память. \en The number of elements the memory is allocated for. 
  uint16  delta; ///< \ru Приращение по количеству элементов при выделении дополнительной памяти. \en Increment by the number of elements while the allocation of additional memory. 
private:
  TPtr *  parr;  ///< \ru Указатель на первый элемент массива. \en A pointer to the first array element. 

public :
  /// \ru Конструктор. \en Constructor. 
  RPArray();
  /// \ru Конструктор. \en Constructor. 
  RPArray ( size_t i_upper, uint16 i_delta = 1 );//, bool shouldNullSet = false );
  /// \ru Деструктор. \en Destructor. 
  virtual ~RPArray();

public:
  
  /// \ru Получить приращение по количеству элементов при выделении дополнительной памяти. \en Get the increment by the number of elements while the allocation of additional memory. 
          uint16  Delta() const { return delta; }
  /// \ru Количество элементов, для которых выделена память? \en The number of elements the memory is allocated for. 
          size_t  Upper() const { return upper; }
  /// \ru Установить приращение по количеству элементов при выделении дополнительной памяти (1 - автоприращение). \en Set the increment by the number of elements while the allocation of additional memory (1 - autoincrement). 
          void    Delta( uint16 newDelta )       { delta = newDelta; }
  /// \ru Установить максимальное из приращений. \en Set the maximum increment. 
          void    SetMaxDelta( uint16 newDelta ) { if ( delta < newDelta ) delta = newDelta; }

  /// \ru Функции, выделяющие потенциально большие участки памяти, возвращают результат операции (успех/ошибка).
  /// \en Functions that allocate potentially large memory, return an operation result (success/error). 
          bool    SetSize ( size_t newSize );                           ///< \ru Установить новый размер массива. \en Set the new size of an array. 
          bool    Reserve ( size_t n, bool addAdditionalSpace = true ); ///< \ru Зарезервировать место под столько элементов. \en Reserve space for a given number of elements. 

          bool    Add     ( Type * );                 ///< \ru Добавить элемент в конец массива. \en Add an element to the end of the array. 
          bool    AddAt   ( Type * e, size_t index ) { return Insert( index, e ); } ///< \ru Вставить элемент в указанную позицию. \en Insert an element to the given position. 
          bool    AddAfter( Type * e, size_t index ); ///< \ru Добавить элемент после указанного. \en Add an element after the specified one. 
          bool    Insert  ( size_t index, Type * );   ///< \ru Вставить элемент перед указанным. \en Insert an element before the specified one. 

          bool    AddArray   ( const RPArray<Type> & );               ///< \ru Добавить массив. \en Add array. 
          bool    AddCArray  ( const Type **, size_t count );         ///< \ru Добавить C-массив. \en Add C-array. 
          bool    InsertArray( const RPArray<Type> &, size_t index ); ///< \ru Добавить массив в позицию. \en Add an array to the position. 

          void    DetachAll();                          ///< \ru Удалить все элементы обнулить количество элементов. \en Delete all elements and set the number of elements to null. 
          void    Adjust();                             ///< \ru Удалить лишнюю память. \en Free the unnecessary memory. 
          Type *  DetachInd( size_t delIndex );         ///< \ru Отсоединить элемент от массива. \en Detach an element from the array. 
          bool    DetachObj( const Type * delObject );  ///< \ru Отсоединить элемент от массива. \en Detach an element from the array. 

  virtual Type *  RemoveInd( size_t delIndex, DelType /*del*/ = defDelete ) { return DetachInd( delIndex); } ///< \ru Удалить элемент из массива по индексу. \en Delete an element from array by the index. 

          void    Swap( RPArray & arr );          ///< \ru Обменять местами данные массивов. \en Swap data of arrays. 

          size_t  FindIt ( const Type * ) const;  ///< \ru Найти элемент по указателю. \en Find an element by a pointer. 
          bool    IsExist( const Type * ) const;  ///< \ru Есть ли элемент в массиве. \en Whether an element belongs the array. 
          size_t  Count() const { return count; } ///< \ru Получить количество элементов массива. \en Get the number of array elements. 
          ptrdiff_t MaxIndex() const { return ((ptrdiff_t)count - 1); } ///< \ru Получить индекс последнего объект в массиве. \en Get the index of the last element in the array. 

  typedef int     (*CompFunc)( const Type **, const Type ** ); ///< \ru Шаблон функции сортировки. \en A template of sorting function. 
          void    Sort ( CompFunc comp ); ///< \ru Сортировать массив. \en Sort the array. 

  /// \ru Оператор доступа по индексу. \en Access by index operator. 
          Type *& operator []( size_t loc ) const;
  /// \ru Получить адрес последнего элемента в массиве. \en Get the address of the last element in the array. 
          Type *  GetLast() const { return ((count > 0) ? parr[count-1] : (Type*)nullptr); }

public: // \ru унификация с вектором STL \en unification with STL vector 
          bool    empty() const { return count == 0; }
          size_t  size() const { return count; }             ///< \ru Дать количество элементов массива. \en Get the number of elements in array. 
          bool    reserve( size_t n ) { return Reserve( n, false ); } ///< \ru Зарезервировать место под столько элементов. \en Reserve space for a given number of elements. 
          size_t  capacity() const { return Upper(); }         ///< \ru Под какое количество элементов выделена память? \en What is the number of elements the memory is allocated for? 
          void    push_back( const Type * e ) { Add( const_cast<Type *>(e) ); } ///< \ru Добавить элемент в конец массива. \en Add an element to the end of the array. 
          void    emplace_back( const Type * e ) { Add( const_cast<Type *>(e) ); } ///< \ru Добавить элемент в конец массива. \en Add an element to the end of the array. 
          template <class Iterator>
          void    insert( Iterator pos, const Type * e ); ///< \ru Вставить элемент перед указанным. \en Insert an element before the specified one. 
  // \ru прописывать поведение у всех классов-наследников! \en define the behavior for all classes-inheritors! 
          template <class Iterator>
          void    erase( Iterator pos );                  ///< \ru Удалить элемент из массива по индексу. \en Delete an element from array by the index. 
          template <class Iterator>
          void    erase( Iterator first, Iterator last ); ///< \ru Удалить элементы из массива начиная с индекса first до last-1 включительно. \en Delete elements from the array from first to last-1 inclusively. 
  virtual void    clear() { DetachAll(); }      ///< \ru Обнулить количество элементов. \en Set the number of elements to null. 
          void    shrink_to_fit() { Adjust(); } ///< \ru Удалить лишнюю память. \en Free the unnecessary memory (Reduce capacity).  
  
  const   TPtr *        begin() const { return parr; } ///< \ru Получить указатель на первый элемент массива. \en Get the pointer to the first array element. 
          TPtr *        begin()       { return parr; } ///< \ru Получить указатель на первый элемент массива. \en Get the pointer to the first array element. 
  const   TPtr *        end()   const { return parr + count; }  ///< \ru Получить указатель на участок памяти после массива. \en Get the pointer to the piece of memory after the array. 
          TPtr *        end()         { return parr + count; }  ///< \ru Получить указатель на участок памяти после массива. \en Get the pointer to the piece of memory after the array.   
  const   TPtr *        cbegin() const { return parr; }       ///< \ru Получить указатель на первый элемент массива. \en Get the pointer to the first array element. 
  const   TPtr *        cend()   const { return parr + count; } ///< \ru Получить указатель на участок памяти после массива. \en Get the pointer to the piece of memory after the array. 
  const   value_type    front()  const;
          value_type &  front();
  const   value_type    back()   const;
          value_type &  back();
        const_reference at( size_t idx ) const;
          reference     at( size_t idx );
  
protected:
  const   Type ** GetAddr() const { return (const Type **)parr; } ///< \ru Получить указатель на первый элемент массива. \en Get the pointer to the first array element. 
  const   TPtr * _Begin()   const { return parr; } ///< \ru Получить указатель на первый элемент массива. \en Get the pointer to the first array element. 
          TPtr * _Begin()         { return parr; } ///< \ru Получить указатель на первый элемент массива. \en Get the pointer to the first array element. 
  const   TPtr * _End()     const { return parr + count; } ///< \ru Получить указатель на участок памяти после массива. \en Get the pointer to the piece of memory after the array. 
         
          bool    CatchMemory();         ///< \ru Захватить память. \en Catch memory. 
          bool    AddMemory( size_t n ); ///< \ru Обеспечить место в памяти под n элементов, независимо от AutoDelta \en Provide memory for n elements, independently from AutoDelta 
          size_t  AutoDelta() const { return ::KsAutoDelta( count, delta ); } ///< \ru Вычислить автоприращение. \en Calculate autoincrement. 
  
private:
  RPArray( const RPArray<Type> & );                     // \ru запрещено !!! \en forbidden !!! 
  RPArray<Type> & operator =( const RPArray<Type> & );  // \ru запрещено !!! \en forbidden !!! 

  TEMPLATE_FRIEND bool    set_Rarray_size TEMPLATE_SUFFIX ( RPArray<Type> &, size_t newSize );
  TEMPLATE_FRIEND size_t  find_in_array   TEMPLATE_SUFFIX ( const RPArray<Type> & arr, const Type * el );
#if defined(_MSC_VER) && !defined(_MSVC_PERMISSIVE_OFF)
  TEMPLATE_FRIEND size_t  find_in_array   TEMPLATE_SUFFIX ( const RPArray<const Type> & arr, const Type * el );
#endif // _MSC_VER 

  TEMPLATE_FRIEND reader & CALL_DECLARATION operator >> TEMPLATE_SUFFIX ( reader & in, RPArray<Type> & ref );
  TEMPLATE_FRIEND writer & CALL_DECLARATION operator << TEMPLATE_SUFFIX ( writer & out, const RPArray<Type> & ref );
  TEMPLATE_FRIEND reader & CALL_DECLARATION operator >> TEMPLATE_SUFFIX ( reader & in, RPArray<Type> *& ptr );         
  TEMPLATE_FRIEND writer & CALL_DECLARATION operator << TEMPLATE_SUFFIX ( writer & out, const RPArray<Type> * ptr );

#ifdef __DEBUG_MEMORY_ALLOCATE_FREE_
public:
  void * operator new    ( size_t );
  void   operator delete ( void *, size_t );
#endif // __DEBUG_MEMORY_ALLOCATE_FREE_

public:
  RPArray( RPArray<Type> && );                     ///< \ru Конструктор перемещения массива. \en Constructor of an array moving.
  RPArray<Type> & operator = ( RPArray<Type> && ); ///< \ru Оператор перемещения массива. \en Operator of an array moving.

};


#ifdef __DEBUG_MEMORY_ALLOCATE_FREE_
//------------------------------------------------------------------------------
// \ru Перегрузка оператора new. \en Overloading of the "new" operator. 
// ---
template <class Type>
inline void * RPArray<Type>::operator new( size_t size ) {
  return ::Allocate( size, typeid(RPArray<Type>).name() );
}

//------------------------------------------------------------------------------
// \ru Перегрузка оператора delete. \en Overloading of the "delete" operator. 
// ---
template <class Type>
inline void RPArray<Type>::operator delete( void * ptr, size_t size ) {
  ::Free( ptr, size, typeid(RPArray<Type>).name() );
}
#endif // __DEBUG_MEMORY_ALLOCATE_FREE_


//------------------------------------------------------------------------------
// \ru конструктор массива \en constructor of an array 
// ---
template <class Type>
inline RPArray<Type>::RPArray()
  : count( 0 )
  , upper( 0 )
  , delta( 1 )
  , parr ( 0 )
{}


//------------------------------------------------------------------------------
// \ru конструктор массива \en constructor of an array 
// ---
template <class Type>
inline RPArray<Type>::RPArray( size_t i_upper, uint16 i_delta )//, bool shouldNullSet )
  : count( 0 )
  , upper( 0 )
  , delta( i_delta )
  , parr ( 0 ) //i_upper ? new TPtr[i_upper] : 0 )
{
  if ( !set_Rarray_size(*this, i_upper) && !ExceptionMode::IsEnabled() )
    throw std::bad_alloc(); // \ru Бросить исключение при любом режиме. \en Throw exception in case of any mode.

  //if ( shouldNullSet && upper > 0 ) {
  //  count = upper;
  //  memset( parr, 0, count * SIZE_OF_POINTER );
  //}
}


//------------------------------------------------------------------------------
// \ru Конструктор перемещения массива. \en Constructor of an array moving.
// ---
template <class Type>
inline RPArray<Type>::RPArray( RPArray<Type> && _Right )
  : count(_Right.count)
  , upper(_Right.upper)
  , delta(_Right.delta)
  , parr (_Right.parr)
{
  _Right.count = 0;
  _Right.upper = 0;
  _Right.delta = 1;
  _Right.parr  = nullptr;
}

//------------------------------------------------------------------------------
// \ru Оператор перемещения массива. \en Operator of an array moving.
// ---
template <class Type>
RPArray<Type> & RPArray<Type>::operator = ( RPArray<Type> && _Right )
{
  if ( this != &_Right )
  {
    set_Rarray_size( *this, 0 );
    _Right.Swap( *this );
  }
  return (*this);
}


//------------------------------------------------------------------------------
// \ru деструктор массива \en destructor of array 
// ---
template <class Type>
inline RPArray<Type>::~RPArray() {
  set_Rarray_size( *this, 0 ); //delete [] parr;
}

//------------------------------------------------------------------------------
// \ru Оператор доступа по индексу. \en Access by index operator. 
// ---
template <class Type>
inline Type *& RPArray<Type>::operator []( size_t loc ) const
{
  return parr[loc];
}

//------------------------------------------------------------------------------
// \ru Доступ к первому элементу. \en Access to the first element. 
// ---
template <class Type>
inline const typename RPArray<Type>::value_type RPArray<Type>::front() const {
  PRECONDITION( !empty() );
  return *parr;
}

//-------------------------------------------------------------------------------
// \ru Доступ к первому элементу. \en Access to the first element. 
// ---
template <class Type>
inline typename RPArray<Type>::value_type & RPArray<Type>::front() {
  PRECONDITION( !empty() );
  return *parr;
}

//-------------------------------------------------------------------------------
// \ru Доступ к последнему элементу. \en Access to the last element. 
// ---
template <class Type>
inline const typename RPArray<Type>::value_type RPArray<Type>::back() const
{
  PRECONDITION( !empty() );
  return *( parr + count - 1 );
}

//-------------------------------------------------------------------------------
// \ru Доступ к последнему элементу. \en Access to the last element. 
// ---
template <class Type>
inline typename RPArray<Type>::value_type & RPArray<Type>::back()
{
  PRECONDITION( !empty() );
  return *( parr + count - 1 );
}

//-------------------------------------------------------------------------------
// \ru Доступ по индексу. \en Access by index operator. 
// ---
template <class Type>
inline typename RPArray<Type>::const_reference RPArray<Type>::at( size_t idx ) const
{
  PRECONDITION( idx < count );
  return parr[idx];
}

//-------------------------------------------------------------------------------
// \ru Доступ по индексу. \en Access by index operator. 
// ---
template <class Type>
inline typename RPArray<Type>::reference RPArray<Type>::at( size_t idx )
{
  PRECONDITION( idx < count );
  return parr[idx];
}

//-------------------------------------------------------------------------------
// \ru обнулить количество элементов \en set the number of elements to null 
// ---
template <class Type>
inline void RPArray<Type>::DetachAll() {
  count = 0;
}


//------------------------------------------------------------------------------
// \ru Указать новый размер массива. \en Set the new size of an array.
// ---
template <class Type>
inline bool RPArray<Type>::SetSize( size_t newSize ) {
  return set_Rarray_size( *this, newSize );
}


//------------------------------------------------------------------------------
// \ru Зарезервировать место под n элементов. \en Reserve memory for n elements. 
// ---
template <class Type>
inline bool RPArray<Type>::Reserve( size_t n, bool addAdditionalSpace ) {
  if ( addAdditionalSpace )
    n += count;
  // \ru Захватить память, если требуется памяти больше, чем есть сейчас. \en if there is required more memory that exists at the moment catch it.
  if ( upper < n ) {
    return set_Rarray_size( *this, n );
  }
  else {
    // C3D_ASSERT( upper <= n ); // Use SetSize!!!
  }
  return true;
}


//------------------------------------------------------------------------------
// \ru Обеспечить место под n элементов, независимо от AutoDelta \en Provide memory for n elements, independently from AutoDelta 
// ---
template <class Type>
inline bool RPArray<Type>::AddMemory( size_t n ) {
  if ( upper - count < n ) {
    return set_Rarray_size( *this, count + n );
  }
  return true;
}


//------------------------------------------------------------------------------
// \ru освободить лишнюю память \en free unnecessary memory 
// ---
template <class Type>
inline void RPArray<Type>::Adjust() {
  if ( count < upper )
    set_Rarray_size( *this, count );
}


//------------------------------------------------------------------------------
// \ru добавить 1 элемент в конец массива \en add 1 element to the end of array 
// ---
template <class Type>
inline bool RPArray<Type>::Add( Type * ent ) {
  if ( CatchMemory() ) {
    parr[count++] = ent;
    return true;
  }
  return false;
}


//------------------------------------------------------------------------------
// \ru добавить 1 элемент после заданного \en add 1 element after the given one 
// ---
template <class Type>
inline bool RPArray<Type>::AddAfter( Type * ent, size_t  index ) {
  if ( !count )
    return Add( ent );
  else {
    if ( CatchMemory() ) {        // \ru добавить памяти, если все использовано \en add memory if whole allocated memory is used 
      if ( index > count - 1 )
        index = count - 1;
      // \ru передвинем вправо все элементы массива с index+1 до последнего \en move to the right all elements of the array from index+1 to the last 
      memmove( parr + index + 2, parr + index + 1, (count - index - 1) * SIZE_OF_POINTER );
      parr[index + 1] = ent; // \ru записываем новый элемент \en writing new element 
      count++;
      return true;
    }
  }
  return false;
}


//------------------------------------------------------------------------------
// \ru добавить массив \en add array 
// \ru эти функции раньше обнуляли признак владения у второго массива, \en These functions set to null the attribute of second element ownership earlier, 
// \ru Теперь об этом нужно заботиться самостоятельно ! \en Now you should take care of it ! 
// ---
template <class Type>
inline bool RPArray<Type>::AddArray( const RPArray<Type> & from ) {
  return AddCArray( from.GetAddr(), from.count );
}


//------------------------------------------------------------------------------
// \ru добавить C-массив \en add C-array 
// ---
template <class Type>
inline bool RPArray<Type>::AddCArray( const Type ** from, size_t fromCount ) {
  if ( fromCount ) {
    if ( AddMemory( fromCount ) ) {  // \ru обеспечить память на такое кол-во элементов \en allocate memory for the given number of elements 
      memcpy( parr + count, from, fromCount * SIZE_OF_POINTER );
      count += fromCount;
      return true;
    }
  }
  return false;
}


//------------------------------------------------------------------------------
// \ru добавить массив в позицию index \en Add an array to the position index 
// \ru (если index>count, то в конец) \en (if 'index' > 'count' then add to the end) 
// \ru эти функции раньше обнуляли признак владения у второго массива, \en These functions set to null the attribute of second element ownership earlier, 
// \ru теперь об этом нужно заботиться самостоятельно ! \en Now you should take care of it ! 
// ---
template <class Type>
inline bool RPArray<Type>::InsertArray( const RPArray<Type> & from, size_t index ) {
  if ( from.count ) {
    if ( index > count )
      index = count;
    if ( AddMemory( from.count ) ) {
      if ( count > index ) // \ru переместить хвост подальше \en move a tale farther 
        memmove( parr + index + from.count, parr + index, (count - index) * SIZE_OF_POINTER );
      memcpy( parr + index, from.parr, from.count * SIZE_OF_POINTER );
      count += from.count;
      return true;
    }
  }
  return false;
}


//------------------------------------------------------------------------------
// \ru вставить 1 элемент перед указанным \en insert 1 element before the specified one 
// ---
template <class Type>
inline bool RPArray<Type>::Insert( size_t index, Type * ent ) {
  if ( CatchMemory() ) {         // \ru добавить памяти, если все использовано \en add memory if whole allocated memory is used 
    if ( index >= count )
      index = count;
    else {
      // \ru передвинем вправо все элементы массива с последнего до указанного \en move to the right all elements of the array from the last to the specified one 
      memmove( parr + index + 1, parr + index, (count - index) * SIZE_OF_POINTER );
    }
    parr[index] = ent;     // \ru записываем новый элемент \en writing new element 
    count++;
    return true;
  }
  return false;
}


//------------------------------------------------------------------------------
// \ru вернуть индекс элемента в массиве \en return an index of the element in the array 
// ---
template <class Type>
inline size_t RPArray<Type>::FindIt( const Type * el ) const 
{
  // \ru MA Linux return find_in_array( *this, el ); // ошибка при сопоставлении шаблонов для RPArray<const Type> \en MA Linux return find_in_array( *this, el ); // an error in matching of templates for RPArray<const Type> 
  if ( parr ) {
    TPtr * iterLast = parr+count;
    TPtr * iter = std::find( parr, iterLast, el );
    if ( iter != iterLast )
    {
      return std::distance( parr, iter );
    }
  }
  return SYS_MAX_T;
}


//------------------------------------------------------------------------------
// \ru Есть ли в массиве такой указатель \en Whether such pointer exists in the array 
// ---
template <class Type>
inline bool RPArray<Type>::IsExist( const Type * el ) const {
  return (FindIt( el ) != SYS_MAX_T);
}


//------------------------------------------------------------------------------
// \ru отсоединить элемент от массива (по индексу) \en detach an element from the array (by the index) 
// ---
template <class Type>
inline Type * RPArray<Type>::DetachInd( size_t delIndex )
{
  Type * r = 0;

  if ( parr ) {
    PRECONDITION( delIndex < count );
    if ( delIndex < count ) {
      r = parr[delIndex];
      memmove( parr + delIndex, parr + delIndex + 1, ( count-- - delIndex - 1 ) * SIZE_OF_POINTER );
    }
  }

  return r;
}


//------------------------------------------------------------------------------
// \ru Вставить элемент перед указанным. \en Insert an element before the specified one. 
// ---
template <class Type>
template <class Iterator>
void RPArray<Type>::insert( Iterator pos, const Type * e )
{
  if ( !begin() ) {
    reserve( 1 );
    pos = begin();
  }
  if ( begin() ) {
    const ptrdiff_t k = std::distance( (Iterator)begin(), pos );
    if ( k >= 0 && k <= (ptrdiff_t)count )
      Insert( k, const_cast<Type *>(e) );
  }
}


//------------------------------------------------------------------------------
// \ru Удалить элемент из массива по индексу. \en Delete an element from array by the index. 
// ---
template <class Type>
template <class Iterator>
void RPArray<Type>::erase( Iterator pos )
{
  if ( begin() ) {
    const ptrdiff_t k = std::distance( (Iterator)begin(), pos );
    if ( k >= 0 && k < (ptrdiff_t)count )
      RemoveInd( k );
  }
}


//------------------------------------------------------------------------------
// \ru Удалить элементы из массива начиная с индекса first до last-1 включительно. \en Delete elements from the array from first to last-1 inclusively. 
// ---
template <class Type>
template <class Iterator>
void RPArray<Type>::erase( Iterator first, Iterator last )
{
  if ( begin() ) {
    const ptrdiff_t k1 = std::distance( (Iterator)begin(), first );
    const ptrdiff_t k2 = std::distance( (Iterator)begin(), last );

    if ( k1 >= 0 && k1 < k2 && k2 <= (ptrdiff_t)count ) {
      for ( ptrdiff_t k = k2-1; k >= k1; k-- ) {
        RemoveInd( k );
      }
    }
  }
}


//------------------------------------------------------------------------------
// \ru отсоединить элемент от массива (по указателю) \en detach an element from the array (by the pointer) 
// ---
template <class Type>
inline bool RPArray<Type>::DetachObj( const Type * delObject ) 
{
  size_t i = FindIt( delObject );
  if ( i != SYS_MAX_T ) 
  {
    DetachInd( i );
    return true;
  }
  return false;
}


//-------------------------------------------------------------------------------
// \ru обменять местами данные массивов \en swap data of arrays 
// ---
template <class Type>
void RPArray<Type>::Swap( RPArray & arr ) {
  std::swap( count, arr.count );
  std::swap( upper, arr.upper );
  std::swap( delta, arr.delta );
  std::swap( parr,  arr.parr  );
}


//------------------------------------------------------------------------------
// \ru захват большего куска памяти ( если нужно ) \en allocate the large piece of memory (if it is necessary) 
// ---
template <class Type>
inline bool RPArray<Type>::CatchMemory() {
  if ( upper == count )
    return set_Rarray_size( *this, upper + AutoDelta() );
  return true;
}


//------------------------------------------------------------------------------
// \ru сортировать массив \en sort the array 
// --- !!!!!!!!!!
template <class Type>
inline void RPArray<Type>::Sort( CompFunc fcmp ) {
  ::KsQSort( (void *)parr, count, SIZE_OF_POINTER, (KsQSortCompFunc)fcmp );
}


//------------------------------------------------------------------------------
// \ru Установить присланный размер массива. Если он меньше имеющегося count, то \en Set the given size of an array. If it is less than existed 'count' then 
// \ru лишние элементы массива будут удалены \en extra elements of the array will be deleted 
// ---
template <class Type>
bool set_Rarray_size( RPArray<Type> & arr, size_t newSize )
{
  if ( newSize != arr.upper ) {
    // \ru половина адресного пространства для 64- и 32-разрядного приложения \en a half of address space for 64- and 32-bit application  
    if ( ::TestNewSize( SIZE_OF_POINTER, newSize ) ) {
      try {
#ifdef __REALLOC_ARRAYS_STATISTIC_
        void * oldParr = arr.parr;
        size_t oldSize = arr.upper;
#endif // __REALLOC_ARRAYS_STATISTIC_

#ifdef USE_REALLOC_IN_ARRAYS
        arr.parr = (typename RPArray<Type>::TPtr *)REALLOC_ARRAY_SIZE( arr.parr, newSize * SIZE_OF_POINTER, false/*clear*/ );
#else
        typename RPArray<Type>::TPtr *p_tmp = newSize ? new typename RPArray<Type>::TPtr[newSize] : 0;

        if ( arr.parr && p_tmp )
          memcpy( p_tmp, arr.parr, (arr.upper < newSize ? arr.upper : newSize) * SIZE_OF_POINTER );

        if ( arr.parr )
          delete[] arr.parr;

        arr.parr = p_tmp;
#endif // USE_REALLOC_IN_ARRAYS

        arr.upper = newSize;
        arr.count = newSize < arr.count ? newSize : arr.count;

#ifdef __REALLOC_ARRAYS_STATISTIC_
        REALLOC_ARRAY_STATISTICS( oldParr, oldSize * SIZE_OF_POINTER, arr.parr, newSize * SIZE_OF_POINTER, 1/*RParray*/ );
#endif // __REALLOC_ARRAYS_STATISTIC_
      }
      catch ( const std::bad_alloc & ) {
        C3D_CONTROLED_THROW;
        return false;
      }
      catch ( ... ) {
        if ( newSize == 0 )// \ru Не смогли корректно удалить arr.parr. \en Failed to delete arr.parr correctly.
          arr.parr = nullptr;
        C3D_CONTROLED_THROW;
        return false;
      }
    }
    else {
      PRECONDITION( false ); // \ru не бывает столько памяти \en incorrect size of memory 
      C3D_CONTROLED_THROW_EX( std::bad_alloc() );
      return false;
    }
  }
  return true;
}


//-------------------------------------------------------------------------------
// \ru найти объект в массиве \en find an object in the array 
// ---
template <class Type>
size_t find_in_array( const RPArray<Type> & arr, const Type * el ) {
  typename RPArray<Type>::TPtr * parr = arr.parr;
  for ( size_t i = 0, c = arr.count; i < c; i++, parr++ )
    if ( *parr == el )
      return i;

  return SYS_MAX_T;
}


#if defined(_MSC_VER) && !defined(_MSVC_PERMISSIVE_OFF) // LF-Linux: ambiguous template specialization
//-------------------------------------------------------------------------------
// \ru найти объект в массиве \en find an object in the array 
// ---
template <class Type>
size_t find_in_array( const RPArray<const Type> & arr, const Type * el ) {
  typename RPArray<const Type>::TPtr * parr = arr.parr;
  for ( size_t i = 0, c = arr.count; i < c; i++, parr++ )
    if ( *parr == el )
      return i;
  return SYS_MAX_T;
}
#endif // _MSC_VER


//------------------------------------------------------------------------------
// \ru Вычислить приращение для массива в зависимости от количества предполагаемых \en Calculate an increment for the array according to the number of assumed 
// \ru объектов в этом массив (делаю так, чтобы захватов памяти было не более 100) - \en objects in this array (so the number of memory captures will not exceed 100) - 
// \ru иначе при количестве объектов 75000 операции с захватом памяти занимают \en otherwise if the number of objects is 75000 then operations with memory captures take 
// \ru бесконечное время \en infinite time 
// ---
inline uint16 CalcArrayDelta( size_t objsCount ) {
  size_t delta = objsCount / 100;
  delta = delta > 65000 ? 50000 : delta > 0 ? delta : 1;
  return (uint16)delta;
}


#endif  // __TEMPL_RP_ARRAY_H
