元组引用的元组?

时间:2014-06-25 18:15:37

标签: c++ sorting iterator

上下文

我正在寻找一种方法来对多个矢量进行串联排序,并发现它比它应该更复杂(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;
}

0 个答案:

没有答案