上下文
我正在寻找一种方法来对多个矢量进行串联排序,并发现它比它应该更复杂(zip_iterator不起作用等等)。
这似乎是我迄今为止发现的最有希望的事情:http://web.stanford.edu/~dgleich/notebook/2006/03/sorting_two_arrays_simultaneou.html
但是,我对此代码还有两个额外的功能:
第二个可能不是问题,但第一个问题就是给我带来麻烦。
问题
我正在添加可变参数模板以允许对任意数量的向量进行排序,因此sort_permute_iter类现在包含一个迭代器元组而不是一个。我可以实现递增/递减/提前罚款来处理这个问题,但是dereference函数应该返回一个引用元组,我不知道如何让它工作。
代码
#include <iterator>
#include <tuple>
#include <boost/iterator/iterator_facade.hpp>
template <class SortIter, class... PermuteIter>
struct sort_permute_iter_types
{
typedef std::tuple<
typename std::iterator_traits<SortIter>::value_type,
typename std::iterator_traits<PermuteIter>::value_type...> value_type;
typedef std::tuple<
typename std::iterator_traits<SortIter>::value_type&,
typename std::iterator_traits<PermuteIter>::value_type&...> ref_type;
};
template <class SortIter, class... PermuteIter>
class sort_permute_iter :
public boost::iterator_facade<
sort_permute_iter<SortIter, PermuteIter...>,
typename sort_permute_iter_types<SortIter, PermuteIter...>::value_type,
std::random_access_iterator_tag,
typename sort_permute_iter_types<SortIter, PermuteIter...>::ref_type,
typename std::iterator_traits<SortIter>::difference_type>
{
public:
sort_permute_iter() { }
sort_permute_iter(SortIter si, PermuteIter... pi) :
_si(si), _pi(pi...) { }
SortIter _si;
std::tuple<PermuteIter...> _pi;
private:
friend class boost::iterator_core_access;
template<class Tuple, std::size_t Size>
struct incrementer
{
static void increment(Tuple& tuple)
{
incrementer<Tuple, Size - 1>::increment(tuple);
++std::get<Size - 1>(tuple);
}
};
template<class Tuple>
struct incrementer<Tuple, 1>
{
static void increment(Tuple& tuple)
{
++std::get<0>(tuple);
}
};
void increment()
{
++_si;
incrementer<decltype(_pi), sizeof...(PermuteIter)>::increment(_pi);
}
template<class Tuple, std::size_t Size>
struct decrementer
{
static void decrement(Tuple& tuple)
{
decrementer<Tuple, Size - 1>::decrement(tuple);
--std::get<Size - 1>(tuple);
}
};
template<class Tuple>
struct decrementer<Tuple, 1>
{
static void decrement(Tuple& tuple)
{
--std::get<0>(tuple);
}
};
void decrement()
{
--_si;
decrementer<decltype(_pi), sizeof...(PermuteIter)>::decrement(_pi);
}
bool equal(sort_permute_iter const& other) const
{
return _si == other._si;
}
typename sort_permute_iter_types<SortIter, PermuteIter...>::ref_type dereference() const
{
return sort_permute_iter_types<SortIter, PermuteIter...>::ref_type(*_si, (*_pi)...); // What to do??? Help!??
}
template<class Tuple, std::size_t Size>
struct advancer
{
static void advance(Tuple& tuple, difference_type n)
{
advancer<Tuple, Size - 1>::advance(tuple, n);
std::get<Size - 1>(tuple) += n;
}
};
template<class Tuple>
struct advancer<Tuple, 1>
{
static void advance(Tuple& tuple, difference_type n)
{
std::get<0>(tuple) += n;
}
};
void advance(difference_type n)
{
_si += n;
advancer<decltype(_pi), sizeof...(PermuteIter)>::advance(_pi, n);
}
difference_type distance_to(sort_permute_iter const& other) const
{
return other._si - _si;
}
};
template <class SortIter, class... PermuteIter>
struct sort_permute_iter_compare :
public std::binary_function<
typename sort_permute_iter_types<SortIter, PermuteIter...>::value_type,
typename sort_permute_iter_types<SortIter, PermuteIter...>::value_type,
bool>
{
typedef typename sort_permute_iter_types<SortIter, PermuteIter...>::value_type T;
bool operator()(const T& t1, const T& t2)
{
return (std::get<0>(t1) < std::get<0>(t2));
}
};
template <class SortIter, class... PermuteIter>
sort_permute_iter<SortIter, PermuteIter...> make_sort_permute_iter(SortIter&& si, PermuteIter&&... pi)
{
return sort_permute_iter<SortIter, PermuteIter...>(std::forward<SortIter>(si), std::forward<PermuteIter>(pi)...);
};
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
std::vector<int> v1{ 3, 1, 0, 2 };
std::vector<int> v2{ 3, 1, 0, 2 };
std::vector<float> v3{ 3.f, 1.f, 0.f, 2.f };
std::sort(
make_sort_permute_iter(v1.data(), v2.data(), v3.data()),
make_sort_permute_iter(v1.data() + v1.size(), v2.data() + v2.size(), v3.data() + v3.size()),
sort_permute_iter_compare<decltype(v1.data()), decltype(v2.data()), decltype(v3.data())>());
for (auto i : v1)
std::cout << i << " ";
std::cout << std::endl;
for (auto i : v2)
std::cout << i << " ";
std::cout << std::endl;
for (auto i : v3)
std::cout << i << " ";
std::cout << std::endl;
}