std: : insertter с набором - вставить в начало () или конец ()? [дубликат]

18
задан AshleysBrain 31 August 2010 в 14:23
поделиться

2 ответа

Вы можете использовать собственный функтор вместо std::inserter и повторно вызывать out.end() каждый раз, когда вставляется новый элемент .

В качестве альтернативы, если ваши значения отсортированы по убыванию, подойдет out.begin().

2
ответ дан 30 November 2019 в 09:36
поделиться

Я выбрал ответ Александра Гесслера как «правильный», потому что он привел меня к этому решению, которое, как я думал, я все равно опубликую. Я написал last_inserter(), который гарантирует, что позиция вставки всегда является итератором для последнего элемента (или begin(), если он пуст), потому что set хочет, чтобы итератор элемент , предшествующий фактической позиции вставки для лучшей производительности (поэтому не end() - это будет единица после фактической позиции вставки).

Использование в соответствии с исходным примером выглядит следующим образом:

std::set<int> s1, s2, out;

// ... s1 and s2 are populated ...

std::set_intersection(s1.begin(), s1.end(),
                      s2.begin(), s2.end(),
                      last_inserter(out));  // note no iterator provided

Это гарантирует, что подсказка вставки всегда является итератором для последнего элемента, что, как мы надеемся, обеспечивает наилучшую производительность при использовании выходного итератора для набора с отсортированным диапазоном. , как указано выше.

Ниже приведена моя реализация. Я думаю, что это зависит от платформы для реализации STL в Visual C++ 2010, потому что он в значительной степени основан на существующем insert_iterator, и я могу заставить его работать, только наследуя от std::_Outit. Если кто-нибудь знает, как сделать это переносимым, дайте мне знать:

// VC10 STL wants this to be a checked output iterator.  I haven't written one, but
// this needs to be defined to silence warnings about this.
#define _SCL_SECURE_NO_WARNINGS

template<class Container>
class last_inserter_iterator : public std::_Outit {
public:
    typedef last_inserter_iterator<Container> _Myt;
    typedef Container container_type;
    typedef typename Container::const_reference const_reference;
    typedef typename Container::value_type _Valty;

    last_inserter_iterator(Container& cont)
        : container(cont)
    {
    }

    _Myt& operator=(const _Valty& _Val)
    {
        container.insert(get_insert_hint(), _Val);
        return (*this);
    }

    _Myt& operator=(_Valty&& _Val)
    {
        container.insert(get_insert_hint(), std::forward<_Valty>(_Val));
        return (*this);
    }

    _Myt& operator*()
    {
        return (*this);
    }

    _Myt& operator++()
    {
        return (*this);
    }

    _Myt& operator++(int)
    {
        return (*this);
    }

protected:
    Container& container;

    typename Container::iterator get_insert_hint() const
    {
        // Container is empty: no last element to insert ahead of; just insert at begin.
        if (container.empty())
            return container.begin();
        else
        {
            // Otherwise return iterator to last element in the container.  std::set wants the
            // element *preceding* the insert position as a hint, so this should be an iterator
            // to the last actual element, not end().
            return (--container.end());
        }
    }
};

template<typename Container>
inline last_inserter_iterator<Container> last_inserter(Container& cont)
{
    return last_inserter_iterator<Container>(cont);
}
5
ответ дан 30 November 2019 в 09:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: