是否允许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>
的其他算法呢?
答案 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
返回右值引用是多余的。