带有移动迭代器的独特算法
unique algorithm with move iterators
是否允许将 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>
中的其他算法呢?
程序保证按标准运行。
std::unique
需要前向迭代器。显示移动迭代器满足该要求的最简单方法是检查 iterator_category
typedef of move_iterator
:
typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
可以看到,直接适配了底层迭代器类型的迭代器类别。事实上,移动迭代器的行为几乎等同于它们的底层行为,[move.iterators]/1:
Class template move_iterator
is an iterator adaptor with the same
behavior as the underlying iterator except that its indirection
operator implicitly converts the value returned by the underlying
iterator’s indirection operator to an rvalue reference.
没有其他值得注意的要求:显然 vector<>::iterator
是一个输入迭代器(根据 [move.iter.requirements] 的要求)。 unique
本身强加的唯一相关要求是
The type of *first
shall satisfy the MoveAssignable
requirements
(Table 22).
... 直接遇到了
请注意,使用移动迭代器不应比普通迭代器带来任何优势。在内部,重复元素是移动分配的(因此 MoveAssignable
要求),因此从 operator*
返回右值引用是多余的。
是否允许将 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>
中的其他算法呢?
程序保证按标准运行。
std::unique
需要前向迭代器。显示移动迭代器满足该要求的最简单方法是检查 iterator_category
typedef of move_iterator
:
typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
可以看到,直接适配了底层迭代器类型的迭代器类别。事实上,移动迭代器的行为几乎等同于它们的底层行为,[move.iterators]/1:
Class template
move_iterator
is an iterator adaptor with the same behavior as the underlying iterator except that its indirection operator implicitly converts the value returned by the underlying iterator’s indirection operator to an rvalue reference.
没有其他值得注意的要求:显然 vector<>::iterator
是一个输入迭代器(根据 [move.iter.requirements] 的要求)。 unique
本身强加的唯一相关要求是
The type of
*first
shall satisfy theMoveAssignable
requirements (Table 22).
... 直接遇到了
请注意,使用移动迭代器不应比普通迭代器带来任何优势。在内部,重复元素是移动分配的(因此 MoveAssignable
要求),因此从 operator*
返回右值引用是多余的。