Files
Extern/C3d/Include/templ_multimap.h
T
SaraP d6eac07eea Extern :
- C3d aggiornamento librerie ( 118019).
2024-12-12 08:37:52 +01:00

700 lines
28 KiB
C++

////////////////////////////////////////////////////////////////////////////////
/**
\file
\brief \ru Мультимножество, реализующее основной функционал std::multimap.
\en Multiset implementing the core functionality of std::multimap. \~
*/
////////////////////////////////////////////////////////////////////////////////
#ifndef __TEMPL_MULTIMAP_H
#define __TEMPL_MULTIMAP_H
#include <templ_s_array.h>
//------------------------------------------------------------------------------
/** \brief \ru Ассоциативное множество c дубликатами (мультимножество).
\en Associative set with duplicates (multiset). \~
\details \ru Ассоциативное множество c дубликатами (мультимножество). \n
Реализует основные функциии std::multimap. Требования к типам данных KeyType и ValType такие же, как в SArray<T>.
Мультимножество задает соответствие (ассоциации) объекта-ключа подмножеству объектов-значений.
Для некоторого объекта типа KeyType задается соответствие подмножеству объектов ValType.
\en Associative set with duplicates (multiset). \n
Implements the core functions of is std::multimap. Requirements to data types KeyType and ValType are the same as in SArray<T>.
Multiset sets the mapping (associations) between a key-object and a subset of value-objects.
For some object of the "KeyType" type there is set a mapping to a subset of objects of the "ValType" type. \~
\ingroup Base_Tools_Containers
*/
// ---
template<class KeyType, class ValType>
class MultiMap {
public:
struct Pair
{
const KeyType m_key;
const ValType m_val;
Pair( const KeyType & key, const ValType & val ) : m_key( key ), m_val( val ) {}
bool operator < ( const Pair & p ) const {
return m_key < p.m_key;
}
bool operator == ( const Pair & p ) const {
return m_key == p.m_key && m_val == p.m_val;
}
Pair & operator = ( const Pair & ); // \ru Не реализовано. \en Not implemented.
};
public:
MultiMap();
virtual ~MultiMap() {}
class Iterator;
public:
/// \ru Оператор доступа по ключу. \en Access by key operator.
Iterator operator[] ( const KeyType & key ) const;
/// \ru Получить итератор, указывающий на первый элемент. \en Get an iterator pointing to the first element.
Iterator First() const;
/// \ru Добавить элемент с заданным ключом и значением. \en Add an element with specified key and value.
void Associate( const KeyType & key, const ValType & val );
/// \ru Удалить заданное значение с заданным ключом. \en Remove an element with specified key and value.
void Dissociate( const KeyType & key, const ValType & val );
/// \ru Удалить элементы в диапазоне [it1, it2). \en Remove elements in the range [it1, it2).
void Dissociate( Iterator & it1, Iterator & it2 );
/// \ru Удалить элемент, указанный итератором. \en Remove an element specified by an iterator.
Iterator Dissociate( Iterator & it );
/// \ru Удалить все элементы из контейнера. \en Removes all elements from the container.
void Flush() { m_Pairs.Flush(); }
/// \ru Существует ли элемент с заданными ключом и значением. \en Is there an element with the specified key and value.
bool IsAssociated( const KeyType & key, const ValType & val ) const;
/// \ru Найти элемент с заданными ключом и значением. \en Find an element with the specified key and value.
Iterator Find( const KeyType & key ) const;
// \ru Итератор, указывающий на первый элемент со значением ключа, не меньшим, чем заданный. \en An iterator pointing to the first element not less than the given key.
Iterator LowerBound( const KeyType & key ) const;
// \ru Итератор, указывающий на первый элемент со значением ключа, большим, чем заданный. \en An iterator pointing to the first element greater than the given key.
Iterator UpperBound( const KeyType & key ) const;
// \ru Диапазон, содержащий все элементы с данным ключом в контейнере. \en A range containing all elements with the given key in the container.
std::pair<Iterator,Iterator> EqualRange( const KeyType & key ) const;
// \ru Количество элементов в контейнере. \en The number of elements in the container.
size_t Count() const { return m_Pairs.Count(); }
static size_t UpperBoundEx( const SArray<Pair> & pairs, const KeyType & key );
static size_t LowerBoundEx( const SArray<Pair> & pairs, const KeyType & key );
static std::pair<size_t,size_t> EqualRangeEx( const SArray<Pair> & pairs, const KeyType & key );
private:
SArray<Pair> m_Pairs;
private: // \ru Специфицируем нуль для разных типов. \en Specify null for different types.
template<class T>
struct Null { // \ru Нуль тривиальных типов (int, float, double и т.д.). \en Null of trivial types (int, float, double etc.).
static inline T val() { return 0; }
};
template<class T>
struct Null<T*> { // \ru Нуль указателей. \en Null of pointers.
static inline T* val() { return nullptr; }
};
// \ru LF_Linux: 25.03.11 g++ выдает ошибку на этот код - не использованы KeyType, ValType в полной специализации шаблона.
// Однако непонятно, зачем нужна эта полная специализация - общая частичная специализация для тривиальных типов вполне подойдет.
// \en LF_Linux: 25.03.11 g++ returns an error in this code - types KeyType and ValType are not used in the full specialization of template.
// But it is not clear what for this specialization is required - the common partial specialization for the trivial types is sufficient.
// template<>
// \ru struct Null<double> { // Нуль вещественных чисел \en struct Null<double> { // Null of real numbers
// static inline double val() { return 0.0; }
// };
public:
// \ru Итератор по элементам контейнера. \en Iterator for the container elements.
class Iterator {
private:
Pair * m_Ptr;
Pair * m_MaxPtr;
public:
Iterator() : m_Ptr( nullptr ), m_MaxPtr( nullptr ) {}
Iterator( const Iterator & iter ) : m_Ptr( iter.m_Ptr ), m_MaxPtr( iter.m_MaxPtr ) {}
Iterator( const SArray<Pair> & m_Pairs, const Pair & pair ) : m_Ptr( nullptr ), m_MaxPtr( nullptr )
{
const size_t count = m_Pairs.Count();
if ( count > 0 ) {
size_t idx = MultiMap<KeyType,ValType>::LowerBoundEx( m_Pairs, pair.m_key );
size_t temp = idx;
while ( temp < m_Pairs.Count() && m_Pairs[temp].m_key == pair.m_key ) {
if ( m_Pairs[temp] == pair ) {
idx = temp;
break;
}
temp++;
}
m_MaxPtr = &m_Pairs[count-1];
if ( idx < count ) {
m_Ptr = &m_Pairs[idx];
}
}
}
Iterator( const SArray<Pair> & m_Pairs, const Iterator & iter1, const Iterator & iter2 ) // range
: m_Ptr( nullptr ), m_MaxPtr( nullptr )
{
const size_t count = m_Pairs.Count();
if ( count > 0 && iter1.m_Ptr != nullptr ) {
size_t idx1 = MultiMap<KeyType,ValType>::LowerBoundEx( m_Pairs, iter1.m_Ptr->m_key );
size_t temp = idx1;
while ( temp < m_Pairs.Count() && m_Pairs[temp].m_key == iter1.m_Ptr->m_key ) {
if ( m_Pairs[temp] == *iter1.m_Ptr ) {
idx1 = temp;
break;
}
temp++;
}
size_t idx2 = SYS_MAX_T;
if ( iter2.m_Ptr != nullptr ) {
idx2 = MultiMap<KeyType,ValType>::UpperBoundEx( m_Pairs, iter2.m_Ptr->m_key );
if ( idx2 < m_Pairs.Count() ) {
if ( idx2 > 0)
idx2--;
else
idx2 = SYS_MAX_T;
}
}
if ( idx2 == SYS_MAX_T )
idx2 = count - 1;
if ( idx1 < count && idx2 < count ) {
m_Ptr = &m_Pairs[idx1];
m_MaxPtr = &m_Pairs[idx2];
}
}
}
public:
/// \ru Получить текущий элемент и сдвинуть итератор на следующий. \en Get the current element and move the iterator to the next.
Iterator operator ++( int )
{
Iterator iter(*this);
if ( m_Ptr && m_Ptr < m_MaxPtr )
m_Ptr++;
else
m_Ptr = 0;
return iter;
}
/// \ru Оператор равенства. \en An equality operator.
bool operator == ( const Iterator & itr ) const
{
if ( Empty() && itr.Empty() )
return true;
if ( ( Empty() && !itr.Empty() ) || ( !Empty() && itr.Empty() ) )
return false;
return m_Ptr == itr.m_Ptr && m_MaxPtr == itr.m_MaxPtr;
}
/// \ru Оператор "!=". \en An "!=" operator.
bool operator != ( const Iterator & itr ) const
{
if ( Empty() && itr.Empty() )
return false;
if ( ( Empty() && !itr.Empty() ) || ( !Empty() && itr.Empty() ) )
return true;
return m_Ptr != itr.m_Ptr || m_MaxPtr != itr.m_MaxPtr;
}
/// \ru Оператор "меньше". \en Operator "less".
bool operator < ( const Iterator& itr ) const
{
return m_Ptr < itr.m_Ptr && m_MaxPtr <= itr.m_MaxPtr;
}
/// \ru Пустой ли итератор. \en Is the iterator empty.
bool Empty() const
{
return !( m_Ptr && m_Ptr <= m_MaxPtr );
}
// \ru Получить текущий ключ элемента. \en Get the current key of the element.
KeyType Key() const
{
return !Empty() ? m_Ptr->m_key : (KeyType)0;
}
// \ru Получить текущее значение элемента. \en Get the current value of the element.
ValType Value() const
{
return !Empty() ? m_Ptr->m_val : (ValType)0; // SKIP_SA
}
// \ru Получить пару с текущим ключом и текущим кзначением элемента. \en Get the pair with the current key and the current value of the element.
Pair* GetPair() const
{
return m_Ptr;
}
};
};
//------------------------------------------------------------------------------
//
// ---
template<class KeyType, class ValType >
size_t MultiMap<KeyType,ValType>::LowerBoundEx( const SArray<typename MultiMap<KeyType,ValType>::Pair> & pairs, const KeyType & key )
{
if ( pairs.Count() > 11 ) {
size_t end = pairs.Count() - 1;
size_t last = end;
size_t start = 0;
size_t firstNotLess = SYS_MAX_T;
while ( start + 1 < end ) { // \ru Ищем, пока не нашли. \en Seek until find.
size_t middle = ( start + end ) / 2;
Pair& mdE = pairs[middle];
if ( mdE.m_key < key ) {
start = middle;
}
else if ( key <= mdE.m_key ) {
if ( middle < firstNotLess )
firstNotLess = middle;
end = middle;
}
// \ru Если попадаем сюда, значит некорректно написаны операторы "тождественно" и сравнения.
// \en If we are here, then operators of identity check and comparison are not correct.
else {
PRECONDITION( 0 );
return SYS_MAX_T;
}
}
// \ru Проверяем ключ между start и end. \en Check a key between start and end.
if ( start + 1 < pairs.Count() - 1 ) {
size_t middle = start + 1;
Pair& mdE = pairs[middle];
if ( key <= mdE.m_key && middle < firstNotLess )
firstNotLess = middle;
}
if ( key <= pairs[0].m_key )
return 0;
if ( firstNotLess <= last && key <= pairs[firstNotLess].m_key )
return firstNotLess;
if ( key == pairs[last].m_key )
return last;
}
else {
if ( pairs.Count() == 1 )
return key <= pairs[0].m_key ? 0 : SYS_MAX_T;
else if ( pairs.Count() == 2 ) {
if ( key <= pairs[0].m_key )
return 0;
if ( key <= pairs[1].m_key )
return 1;
}
else { // 2 < count <= 11
for( size_t i = 0; i < pairs.Count(); ++i )
if ( key <= pairs[i].m_key )
return i;
}
}
return SYS_MAX_T;
}
//------------------------------------------------------------------------------
// \ru Итератор, указывающий на первый элемент со значением ключа, не меньшим, чем заданный.
// \en An iterator pointing to the first element not less than the given key.
// ---
template<class KeyType, class ValType >
inline typename MultiMap<KeyType,ValType>::Iterator MultiMap<KeyType,ValType>::LowerBound( const KeyType & key ) const
{
size_t idx = LowerBoundEx ( m_Pairs, key );
return idx < m_Pairs.Count() ? Iterator ( m_Pairs, m_Pairs[idx] ) : Iterator();
}
template<class KeyType, class ValType >
size_t MultiMap<KeyType,ValType>::UpperBoundEx( const SArray<typename MultiMap<KeyType,ValType>::Pair> & pairs, const KeyType & key )
{
if ( pairs.Count() > 11 ) {
size_t end = pairs.Count() - 1;
size_t last = end;
size_t start = 0;
size_t firstGreater = SYS_MAX_T;
while ( start + 1 < end ) { // \ru Ищем, пока не нашли. \en Seek until find.
size_t middle = ( start + end ) / 2;
Pair& mdE = pairs[middle];
if ( mdE.m_key <= key ) {
start = middle;
}
else if ( key < mdE.m_key ) {
if ( middle < firstGreater )
firstGreater = middle;
end = middle;
}
// \ru Если попадаем сюда, значит некорректно написаны операторы "тождественно" и сравнения.
// \en If we are here, then operators of identity check and comparison are not correct.
else {
PRECONDITION( 0 );
return SYS_MAX_T;
}
}
if ( key < pairs[0].m_key )
return 0;
if ( firstGreater <= end && key < pairs[firstGreater].m_key )
return firstGreater;
if ( key < pairs[last].m_key )
return last;
}
else {
if ( pairs.Count() == 1 )
return key < pairs[0].m_key ? 0 :SYS_MAX_T;
else if ( pairs.Count() == 2 ) {
if ( key < pairs[0].m_key )
return 0;
if ( key < pairs[1].m_key )
return 1;
}
else { // 2 < count <= 11
for( size_t i = 0; i < pairs.Count(); ++i )
if ( key < pairs[i].m_key )
return i;
}
}
return SYS_MAX_T;
}
//------------------------------------------------------------------------------
// \ru Итератор, указывающий на первый элемент со значением ключа, большим, чем заданный.
// \en An iterator pointing to the first element greater than the given key.
// ---
template<class KeyType, class ValType >
inline typename MultiMap<KeyType,ValType>::Iterator MultiMap<KeyType,ValType>::UpperBound( const KeyType & key ) const
{
size_t ind = UpperBoundEx ( m_Pairs, key );
return ind != SYS_MAX_T ? Iterator ( m_Pairs, m_Pairs[ind] ) : Iterator();
}
//------------------------------------------------------------------------------
//
// ---
template<class KeyType, class ValType >
std::pair<size_t,size_t> MultiMap<KeyType, ValType>::EqualRangeEx( const SArray<typename MultiMap<KeyType, ValType>::Pair> & pairs, const KeyType & key )
{
if ( pairs.Count() > 11 ) {
size_t end = pairs.Count() - 1;
size_t lastRight = end;
size_t start = 0;
size_t firstNotLess = SYS_MAX_T;
size_t firstGreater = SYS_MAX_T;
// \ru Проверяем последний элемент. \en Check the last element.
if ( key > pairs[pairs.Count() - 1].m_key )
return std::pair<size_t,size_t> (SYS_MAX_T, SYS_MAX_T);
// \ru Проверяем первый элемент. \en Check the first element.
if ( key < pairs[0].m_key )
return std::pair<size_t,size_t> (0, 0);
if ( key != pairs[0].m_key ) {
while ( start + 1 < end ) { // \ru Ищем, пока не нашли. \en Seek until find.
size_t middle = ( start + end ) / 2;
Pair& mdE = pairs[middle];
if ( mdE.m_key < key ) {
start = middle;
}
else if ( key <= mdE.m_key ) {
if ( key < mdE.m_key && lastRight > middle )
lastRight = middle;
if ( middle < firstNotLess )
firstNotLess = middle;
end = middle;
}
// \ru Если попадаем сюда, значит некорректно написаны операторы "тождественно" и сравнения.
// \en If we are here, then operators of identity check and comparison are not correct.
else {
PRECONDITION( 0 );
return std::pair<size_t,size_t> (SYS_MAX_T, SYS_MAX_T);
}
}
}
else
firstNotLess = 0; // key == pairs[0].m_key
// \ru Проверяем ключ между start и end. \en Check a key between start and end.
if ( start + 1 == end ) {
size_t middle = start + 1;
Pair& mdE = pairs[middle];
if ( key <= mdE.m_key && middle < firstNotLess )
firstNotLess = middle;
}
// \ru Проверяем последний элемент. \en Check the last element.
if ( firstNotLess == SYS_MAX_T && key == pairs[pairs.Count() - 1].m_key )
return std::pair<size_t,size_t> (pairs.Count() - 1, SYS_MAX_T);
if ( firstNotLess == SYS_MAX_T )
return std::pair<size_t,size_t> (SYS_MAX_T, SYS_MAX_T);
// \ru Теперь начинаем правый поиск. \en Now start right search.
end = lastRight;
start = firstNotLess;
if ( start == end && pairs[firstNotLess].m_key != key )
return std::pair<size_t,size_t> ( firstNotLess, firstNotLess );
while ( start + 1 < end ) { // \ru Ищем, пока не нашли. \en Seek until find.
size_t middle = ( start + end ) / 2;
Pair& mdE = pairs[middle];
if ( mdE.m_key <= key ) {
start = middle;
}
else if ( key < mdE.m_key ) {
if ( middle < firstGreater )
firstGreater = middle;
end = middle;
}
// \ru Если попадаем сюда, значит некорректно написаны операторы "тождественно" и сравнения.
// \en If we are here, then operators of identity check and comparison are not correct.
else {
PRECONDITION( 0 );
return std::pair<size_t, size_t> ( SYS_MAX_T, SYS_MAX_T );
}
}
if ( firstGreater == SYS_MAX_T )
{
if ( pairs[firstNotLess].m_key != key )
firstGreater = firstNotLess;
else if ( lastRight > 0 && pairs[lastRight - 1].m_key == key && pairs[lastRight].m_key != key )
firstGreater = lastRight;
else if ( firstNotLess + 1 < pairs.Count() && pairs[firstNotLess + 1].m_key != key )
firstGreater = firstNotLess + 1;
}
return std::pair<size_t,size_t> ( firstNotLess, firstGreater );
}
else {
if ( pairs.Count() == 0 )
return std::pair<size_t, size_t> ( SYS_MAX_T, SYS_MAX_T );
if ( pairs.Count() == 1 )
return key == pairs[0].m_key ? std::pair<size_t, size_t> ( 0, SYS_MAX_T ) :
( key < pairs[0].m_key ? std::pair<size_t, size_t> ( 0, 0 ) : std::pair<size_t, size_t> ( SYS_MAX_T, SYS_MAX_T ) );
if ( pairs.Count() == 2 ) {
size_t first = SYS_MAX_T;
if ( key < pairs[0].m_key )
return std::pair<size_t, size_t>(0, 0);
if ( key > pairs[1].m_key )
return std::pair<size_t, size_t>(SYS_MAX_T, SYS_MAX_T);
if ( key == pairs[0].m_key )
first = 0;
else if ( key == pairs[1].m_key )
first = 1;
else // ( key > pairs[0].m_key && key < pairs[1].m_key )
return std::pair<size_t, size_t> ( 1, 1 );
if ( key == pairs[1].m_key )
return std::pair<size_t ,size_t> ( first, SYS_MAX_T );
return std::pair<size_t, size_t> (first, 1);
}
else { // 2 < count <= 11
size_t first = SYS_MAX_T, second = SYS_MAX_T;
if ( key < pairs[0].m_key )
return std::pair<size_t, size_t> ( 0, 0 );
if ( key > pairs[pairs.Count() - 1].m_key )
return std::pair<size_t, size_t> ( first, second );
for( size_t i = 0; i < pairs.Count(); ++i ) {
if ( key == pairs[i].m_key ) {
if ( first == SYS_MAX_T )
first = i;
}
else {
if ( key < pairs[i].m_key ) {
second = i;
break;
}
}
}
if ( first == SYS_MAX_T )
first = second;
return std::pair<size_t, size_t> ( first, second );
}
}
}
//------------------------------------------------------------------------------
// \ru Диапазон, содержащий все элементы с данным ключом в контейнере.
// \en A range containing all elements with the given key in the container.
// ---
template<class KeyType, class ValType >
inline std::pair<typename MultiMap<KeyType,ValType>::Iterator,typename MultiMap<KeyType,ValType>::Iterator>
MultiMap<KeyType, ValType>::EqualRange ( const KeyType & key ) const
{
std::pair<size_t, size_t> idx = EqualRangeEx ( m_Pairs, key );
Iterator first, second;
if ( idx.first < m_Pairs.Count() )
first = Iterator ( m_Pairs, m_Pairs[idx.first]);
if ( idx.second < m_Pairs.Count() )
second = Iterator ( m_Pairs, m_Pairs[idx.second]);
return std::pair<Iterator, Iterator> ( first, second );
}
//------------------------------------------------------------------------------
/// \ru Найти элемент с заданными ключом и значением.
// \en Find an element with the specified key and value.
// ---
template<class KeyType, class ValType >
inline typename MultiMap<KeyType,ValType>::Iterator MultiMap<KeyType,ValType>::Find( const KeyType & key ) const
{
if ( m_Pairs.Count() > 11 ) {
size_t mx = m_Pairs.Count() - 1;
size_t mxc = mx;
size_t mn = 0;
while ( mn + 1 < mx ) { // \ru Ищем, пока не нашли. \en Seek until find.
size_t md = ( mn + mx ) / 2;
Pair& mdE = m_Pairs[md];
if ( mdE.m_key < key ) {
mn = md;
}
else if ( key < mdE.m_key ) {
mx = md;
}
else if ( mdE.m_key == key )
return Iterator ( m_Pairs, mdE );
// \ru Если попадаем сюда, значит некорректно написаны операторы "тождественно" и сравнения.
// \en If we are here, then operators of identity check and comparison are not correct.
else {
PRECONDITION( 0 );
return Iterator();
}
}
if ( key == m_Pairs[0].m_key )
return Iterator ( m_Pairs, m_Pairs[0] );
if ( key == m_Pairs[mxc].m_key )
return Iterator ( m_Pairs, m_Pairs[mxc] );
}
else {
if ( m_Pairs.Count() == 1 )
return key == m_Pairs[0].m_key ? Iterator ( m_Pairs, m_Pairs[0] ) : Iterator();
else if ( m_Pairs.Count() == 2 ) {
if ( key == m_Pairs[0].m_key )
return Iterator ( m_Pairs, m_Pairs[0] );
if ( key == m_Pairs[1].m_key )
return Iterator ( m_Pairs, m_Pairs[1] );
return Iterator();
}
else { // 2 < count <= 11
for( size_t i = 0; i < m_Pairs.Count(); ++i )
if ( key == m_Pairs[i].m_key )
return Iterator ( m_Pairs, m_Pairs[i] );
}
}
return Iterator();
}
//-------------------------------------------------------------------------------
// \ru Конструктор. \en Contructor.
// ---
template<class KeyType, class ValType >
MultiMap<KeyType,ValType>::MultiMap()
: m_Pairs( 0, 1 )
{}
//-------------------------------------------------------------------------------
/// \ru Добавить элемент с заданным ключом и значением.
// \en Add an element with specified key and value.
// ---
template<class KeyType, class ValType >
inline void MultiMap<KeyType,ValType>::Associate( const KeyType & key, const ValType & val ) {
Pair pair( key, val );
std::pair<size_t, size_t> idx = EqualRangeEx ( m_Pairs, key );
if ( idx.second < m_Pairs.Count() )
m_Pairs.InsertInd ( idx.second, pair );
else
m_Pairs.Add ( pair );
}
//-------------------------------------------------------------------------------
// \ru Существует ли элемент с заданными ключом и значением.
// \en Is there an element with the specified key and value.
// ---
template<class KeyType, class ValType >
inline bool MultiMap<KeyType,ValType>::IsAssociated( const KeyType & key, const ValType & val ) const {
return m_Pairs.FindIt( Pair(key, val) ) < m_Pairs.Count();
}
//-------------------------------------------------------------------------------
/// \ru Удалить заданное значение с заданным ключом. \en Remove an element with specified key and value.
// ---
template<class KeyType, class ValType >
inline void MultiMap<KeyType,ValType>::Dissociate( const KeyType & key, const ValType & val ) {
Pair pair( key, val );
size_t idx = m_Pairs.FindIt( pair );
if ( idx < m_Pairs.Count() ) {
m_Pairs.RemoveInd( idx );
}
}
//-------------------------------------------------------------------------------
/// \ru Удалить элемент, указанный итератором. \en Remove an element specified by an iterator.
// ---
template<class KeyType, class ValType >
inline typename MultiMap<KeyType,ValType>::Iterator MultiMap<KeyType,ValType>::Dissociate(
typename MultiMap<KeyType,ValType>::Iterator & it )
{
size_t idx = m_Pairs.FindIt( *it.GetPair() );
if ( idx < m_Pairs.Count() ) {
m_Pairs.RemoveInd( idx );
if ( idx < m_Pairs.Count() )
return Iterator ( m_Pairs, m_Pairs[idx]);
}
return Iterator();
}
//-------------------------------------------------------------------------------
/// \ru Удалить элементы в диапазоне [it1, it2). \en Remove elements in the range [it1, it2).
// ---
template<class KeyType, class ValType >
inline void MultiMap<KeyType,ValType>::Dissociate(
typename MultiMap<KeyType,ValType>::Iterator & it1,
typename MultiMap<KeyType,ValType>::Iterator & it2 )
{
if ( m_Pairs.Count() == 0 || it1.Empty() )
return;
if ( it2.Empty() ) {
// \ru Удаляем с it1 до конца. \en Remove from it1 up to the end.
it2 = Iterator ( m_Pairs, m_Pairs[m_Pairs.Count() - 1] );
if ( it1 == it2 )
Dissociate ( it1.Key(), it1.Value() ); // \ru Просто удаляем последний элемент. \en Just remove the last element.
else if ( it1 < it2 ) {
size_t idx = m_Pairs.FindIt( *it1.GetPair() );
if ( idx != SYS_MAX_T )
m_Pairs.RemoveInd ( idx, m_Pairs.Count () );
}
}
else if ( it1 < it2 )
m_Pairs.Remove ( it1.GetPair(), it2.GetPair() );
}
//-------------------------------------------------------------------------------
/// \ru Оператор доступа по ключу. \en Access by key operator.
// ---
template<class KeyType, class ValType >
inline typename MultiMap<KeyType,ValType>::Iterator MultiMap<KeyType,ValType>::operator[] ( const KeyType & key ) const {
return Iterator( m_Pairs, Pair(key, Null<ValType>::val()) );
}
//-------------------------------------------------------------------------------
/// \ru Получить итератор, указывающий на первый элемент. \en Get an iterator pointing to the first element.
// ---
template<class KeyType, class ValType >
inline typename MultiMap<KeyType,ValType>::Iterator MultiMap<KeyType,ValType>::First() const {
if ( m_Pairs.Count() )
return Iterator ( m_Pairs, m_Pairs[0] );
return Iterator();
}
#endif // __TEMPL_MULTIMAP_H