Ori*_*ent 6 c++ algorithm iterator stl c++14
是否允许使用std::unique通过函数创建的迭代器std::make_move_iterator?我尝试了以下,并取得了成功:
#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;
}
Run Code Online (Sandbox Code Playgroud)
但也许是依赖于实现的成功?
什么关于其他算法<numeric>和<algorithm>?
该计划保证按标准运作.
std::unique需要前向迭代器.显示移动迭代器满足该要求的最简单方法是检查以下类型的iterator_categorytypedef move_iterator:
typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
Run Code Online (Sandbox Code Playgroud)
如您所见,底层迭代器类型的迭代器类别是直接调整的.实际上,移动迭代器的行为几乎等同于它们的基础行为,[move.iterators]/1:
类模板
move_iterator是一个迭代器适配器,具有与底层迭代器相同的行为,除了它的间接运算符隐式地将底层迭代器的间接运算符返回的值转换为右值引用.
没有其他值得注意的要求:显然vector<>::iterator是一个输入迭代器(根据[move.iter.requirements]的要求).唯一相关的要求unique本身就是
类型
*first应满足MoveAssignable要求(表22).
......这是直截了当的.
请注意,使用移动迭代器不应该比普通迭代器带来任何优势.在内部,重复元素是移动分配的(因此MoveAssignable需求),因此返回rvalue引用operator*是多余的.