General erase function

I need to remove elements of different stl and enhance containers using an iterator. Sometimes I also need to do this with reverse_iterator, so I would like to wrap this in a generic function (set).

According to this: Iterator invalidation rules are basically possible.

What I got so far:

    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()));
}

      

This should work in most cases, but for example a vector-like container that does not return an iterator will break this. Sets do not invalidate any other iterators -> ok to use the next iterator. For vectors, I will need to keep the previous iterator (if any) and return it. For a deck (and similar) without returning an iterator, this won't work at all. I don't want to use EraseImpl for all known containers, for example, it would require me to include all their headers that I want to avoid.

Is there anything I can to avoid specializing for all types? Of course, I can create a trait with an enum like {Use_Next, Use_Prev} and leave it non-specialized for containers that are invalid on all iterators. But then again: I don't want to include every possible heading.

+3


source to share


1 answer


The solution I'm using now is to use a trait class, which can be specialized for each container class.

The default is Not Allowed, but it also provides specializations for containers that have an erase function that returns an iterator. This is done in a general way, so only the existence of such a function is checked. If found, generic_erase uses it. If this flag does not ask the user for specialized what does erase for iterators (next_iterator_valid, prev_iterator_valid, all_invalid) and generic_erase, acts accordingly.



It was useful for this task: Check function signature also for inherited functions

0


source







All Articles