具有移动迭代器的独特算法

时间:2015-01-28 17:54:23

标签: c++ algorithm stl iterator c++14

是否允许std::unique使用通过std::make_move_iterator函数创建的迭代器?我尝试了the following,并取得了成功:

#include <iostream>
#include <ostream>
#include <vector>
#include <algorithm>
#include <limits>
#include <iterator>

#include <cstdlib>

struct A
{

    A() : i(std::numeric_limits< double >::quiet_NaN()) { std::cout << __PRETTY_FUNCTION__ << "\n"; }
    A(double ii) : i(ii) { std::cout << __PRETTY_FUNCTION__ << "\n"; }
    A(A const & a) : i(a.i) { std::cout << __PRETTY_FUNCTION__ << "\n"; }
    A(A && a) : i(std::move(a.i)) { std::cout << __PRETTY_FUNCTION__ << "\n"; a.i = std::numeric_limits< double >::quiet_NaN(); }
    A & operator = (A const & a) { std::cout << __PRETTY_FUNCTION__ << "\n"; i = a.i; return *this; }
    A & operator = (A && a) { std::cout << __PRETTY_FUNCTION__ << "\n"; i = std::move(a.i); a.i = std::numeric_limits< double >::quiet_NaN(); return *this; }
    bool operator < (A const & a) const { std::cout << __PRETTY_FUNCTION__ << "\n"; return (i < a.i); }
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wfloat-equal"
    bool operator == (A const & a) const { std::cout << __PRETTY_FUNCTION__ << "\n"; return (i == a.i); }
#pragma clang diagnostic pop

    friend
    std::ostream &
    operator << (std::ostream & o, A const & a)
    {
        return o << a.i;
    }

private :

    double i;

};

int
main()
{
    std::vector< A > v{1.0, 1.0, 2.0, 2.0, 2.0, 3.0, 4.0, 4.0, 5.0, 6.0, 6.0, 7.0};
    std::cout << "v constructed\n\n\n\n";
    std::sort(v.begin(), v.end());
    auto const end = std::unique(std::make_move_iterator(v.begin()), std::make_move_iterator(v.end())).base();
    std::copy(v.begin(), end, std::ostream_iterator< A >(std::cout, " "));
    std::cout << std::endl;
    return EXIT_SUCCESS;
}

但也许是依赖于实现的成功?

关于<numeric><algorithm>的其他算法呢?

1 个答案:

答案 0 :(得分:5)

该计划保证按标准运作 std::unique需要前向迭代器。显示移动迭代器满足该要求的最简单方法是检查iterator_category的{​​{1}} typedef:

move_iterator

如您所见,底层迭代器类型的迭代器类别是直接调整的。事实上,移动迭代器的行为几乎等同于它们的基础行为,[move.iterators] / 1:

  

类模板typedef typename iterator_traits<Iterator>::iterator_category iterator_category; 是一个具有相同的迭代器适配器   作为底层迭代器的行为,除了它的间接性   operator隐式转换底层返回的值   迭代器的间接运算符到右值引用。

没有其他值得注意的要求:显然move_iterator是一个输入迭代器(根据[move.iter.requirements]的要求)。 vector<>::iterator本身强加的唯一相关要求是

  

unique的类型应满足*first的要求   (表22)。

......这很简单。

请注意,使用移动迭代器不应该比普通迭代器带来任何优势。在内部,重复元素是移动分配的(因此MoveAssignable要求),因此从MoveAssignable返回右值引用是多余的。