给定两个容器:
但是我无法为struct P提供基于P::swap的免费swap函数。这是语言的无法避免的限制(我无法在函数作用域内定义非lambda函数,但可以定义非模板类)。
额外信息:
我发现存在对swap自由函数重载的要求并不是std::sort函数的类型要求。只有MoveConstructible和MoveAssignable是必须的。因此the code更为合适(但仍不完整)。真正困难的问题是:提供给std::sort的范围中元素的交换(显然)被分成一系列组成操作:
std::list< int > a;
和 std::list< int > b;
,— a.size() == b.size()
。需要同步地对容器a
和b
进行排序,即在a
中进行元素交换时,应该对应交换b
中相应的元素(在位置索引的意义上)。假设a
和b
中的元素非常重,即你不能复制它们。
如何以完美的STL方式实现这一操作?如何使用std::sort
来完成操作?如果a
是const
,该怎么办?
我目前的做法:
#include <iostream>
#include <iomanip>
#include <type_traits>
#include <utility>
#include <iterator>
#include <algorithm>
#include <list>
#include <vector>
#include <cstdlib>
#include <cassert>
template< typename first, typename second >
void
sort_synchronously(first & f, second & s)
{
std::size_t sz = f.size();
assert(sz == s.size());
struct P
{
typename first::iterator pfirst;
typename second::iterator psecond;
bool operator < (P const & p) const { return (*pfirst < *p.pfirst); }
void swap(P & p) noexcept { std::iter_swap(pfirst, p.pfirst); std::swap(pfirst, p.pfirst); std::iter_swap(psecond, p.psecond); std::swap(psecond, p.psecond); }
};
std::vector< P > p;
p.reserve(sz); // O(N) additional memory
auto fi = std::begin(f);
auto si = std::begin(s);
for (std::size_t i = 0; i < sz; ++i) {
p.push_back({fi, si});
++fi;
++si;
}
std::sort(std::begin(p), std::end(p)); // O(N * log N) time
}
int
main()
{
std::list< int > a{5, 4, 3, 2, 1};
std::list< int > b{1, 2, 3, 4, 5};
std::copy(std::cbegin(a), std::cend(a), std::ostream_iterator< int >(std::cout, " ")); std::cout << std::endl;
std::copy(std::cbegin(b), std::cend(b), std::ostream_iterator< int >(std::cout, " ")); std::cout << std::endl;
sort_synchronously(a, b);
std::copy(std::cbegin(a), std::cend(a), std::ostream_iterator< int >(std::cout, " ")); std::cout << std::endl;
std::copy(std::cbegin(b), std::cend(b), std::ostream_iterator< int >(std::cout, " ")); std::cout << std::endl;
return EXIT_SUCCESS;
}
但是我无法为struct P提供基于P::swap的免费swap函数。这是语言的无法避免的限制(我无法在函数作用域内定义非lambda函数,但可以定义非模板类)。
额外信息:
我发现存在对swap自由函数重载的要求并不是std::sort函数的类型要求。只有MoveConstructible和MoveAssignable是必须的。因此the code更为合适(但仍不完整)。真正困难的问题是:提供给std::sort的范围中元素的交换(显然)被分成一系列组成操作:
T tmp(std::move(lhs)); lhs = std::move(rhs); rhs = std::move(tmp);
。因此,我不能交换容器本身引用元素的位置(在std::sort期间),而只能交换它们的迭代器。
boot::zip_iterator
不符合排序迭代器的要求 :-( - Jarod42