2015-08-04 11 views
3

Мне нужно удалить элементы разных stl и форсировать контейнеры с помощью итератора. Иногда мне также нужно сделать это с помощью reverse_iterator, поэтому я хотел бы обернуть это в общую функцию (установить).Общая функция стирания

В соответствии с этим: Iterator invalidation rules в основном это возможно.

То, что я получил до сих пор это:

template<class T, bool T_IterReturned = helpers::EraseReturnsIterator<T>::value> 
    struct EraseImpl 
    { 
     typedef typename T::iterator iterator; 
     typedef typename T::const_iterator const_iterator; 
     static iterator erase(list& container, iterator it) { 
      return container.erase(it); 
     } 
     static const_iterator erase(list& container, const_iterator it) { 
      return container.erase(it); 
     } 
    }; 
    template<class T> 
    struct EraseImpl<T, false> 
    { 
     // This one gets used for e.g. std::set whos erase does not return 
     // an iterator until C++11 
     typedef typename T::iterator iterator; 
     typedef typename T::const_iterator const_iterator; 
     static iterator erase(list& container, iterator it) { 
      container.erase(it++); 
      return it; 
     } 
     static const_iterator erase(list& container, const_iterator it) { 
      container.erase(it++); 
      return it; 
     } 
    }; 

template<typename T> 
inline typename T::iterator erase(T& container, typename T::iterator it) 
{ 
    return detail::EraseImpl<T>::erase(container, it); 
} 

template<typename T> 
inline typename T::reverse_iterator erase(T& container, typename T::reverse_iterator it) 
{ 
    typename T::reverse_iterator tmp = it; 
    return typename T::reverse_iterator(erase(container, (++tmp).base())); 
} 

Это должно работать в большинстве случаев, но, например, вектор-подобный контейнер, который не возвращает итератор, нарушит это. Наборы не делают недействительными любые другие итераторы -> ok для использования следующего итератора. Для векторов мне нужно будет сохранить предыдущий итератор (если есть) и вернуть его. Для дека (и аналогичного) без возврата итератора это не будет работать вообще. Я не хочу использовать EraseImpl для всех известных контейнеров, например, это потребовало бы, чтобы я включил все их заголовки, которых я хочу избежать.

Есть ли что-нибудь, что я могу, чтобы избежать его специализации для всех типов? Конечно, я могу создать черту с перечислением типа {Use_Next, Use_Prev} и оставить его неспециализированным для контейнеров, недействительных на всех итераторах. Но опять же: я не хочу включать все возможные заголовки.

+0

Вам не нужно, чтобы включить все заголовки, опережающее объявление достаточно для признаков. – Jarod42

+1

@ Jarod42: Вы не можете форматировать объявления стандартных типов библиотеки. Вот почему есть специальный ''. Однако это единственный такой заголовок. – MSalters

+0

Я подозреваю, что нет общего решения. Как вы будете иметь дело с контейнером, который недействителен _all_ iterators на 'erase'? Не то, что надуманно; векторный контейнер, который сжимается, может это сделать. (Перераспределение на меньший блок) – MSalters

ответ

0

Решение В настоящее время я использую класс признаков, который может быть специализирован для каждого класса контейнера.

По умолчанию «Не разрешено», но также предоставляет специализации для контейнеров, которые имеют функцию стирания, которая возвращает итератор. Это делается в общем виде, поэтому проверяется только существование такой функции. Если он найден, generic_erase использует его. Если нет, то задание запрашивает у пользователя специализированную информацию о том, что делает стирание для итераторов (next_iterator_valid, prev_iterator_valid, all_invalid) и generic_erase.

Это был полезен для выполнения этой задачи: Check for function signature also for inherited functions