ソートせずにコンテナを unique にする

ソートしてもいいなら

std::sort(v.begin(), v.end());
v.erase(std::unique(v.begin(), v.end()), v.end());

でいいんだけど、ソートしたくない場合はどうするんだろうとか思ったわけです。


でまあ、自前でアルゴリズム書くとか無理ゲーなので、こんな風にしました。

// イテレータ経由で比較する
struct direct_less
{
    template<class Iterator>
    bool operator()(const Iterator& a, const Iterator& b) const
    {
        return *a < *b;
    }
};

template<class Iterator, class OutputIterator>
OutputIterator unique_no_sort(Iterator first, Iterator last, OutputIterator out)
{
    // 要素を格納するのは無駄なのでイテレータを格納する
    std::set<Iterator, direct_less> set;
    for (; first != last; ++first)
    {
        if (set.insert(first).second)
            *out++ = *first;
    }
    return out;
}

// イテレータ経由で Compare する
template<class Compare>
struct direct_less_comp
{
    template<class Iterator>
    bool operator()(const Iterator& a, const Iterator& b) const
    {
        return Compare()(*a, *b);
    }
};

template<class Iterator, class OutputIterator, class Compare>
OutputIterator unique_no_sort(Iterator first, Iterator last, OutputIterator out, Compare)
{
    std::set<Iterator, direct_less_comp<Compare> > set;
    for (; first != last; ++first)
    {
        if (set.insert(first).second)
            *out++ = *first;
    }
    return out;
}
int main()
{
    int values[] = { 3, 1, 3, 2, 5, 4, 2, 3, 3, 1, 0, 4, 5 };
    
    std::vector<int> v(values, values + sizeof(values) / sizeof(values[0]));
    std::vector<int> result;
    unique_no_sort(v.begin(), v.end(), std::back_inserter(result));
    for (std::vector<int>::iterator it = result.begin(); it != result.end(); ++it)
    {
        std::cout << *it << " ";
    }
}
3 1 2 5 4 0 

set 使って重複を検出するだけ。
Boost.MultiIndex とか使って sequential で ordered_unique なコンテナにぶち込めばそれでいけそうな気がする。