c++ - 如何使用 boost::joined_range 实现范围适配器

标签 c++ boost boost-range

这是一个基于 Implement a Range Adaptor with arguments 的范围适配器示例:

#include <boost/range/join.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/iterator/permutation_iterator.hpp>
#include <vector>
#include <list>
#include <iterator>
#include <iostream>

template <typename Range, typename Index>
class permutation_range :
        public boost::iterator_range<
                boost::permutation_iterator<
                        typename boost::range_iterator<Range>::type,
                        typename boost::range_iterator<Index>::type>>
{
    using value_type = typename boost::range_value<Range>::type;
    using replaced_iterator = boost::permutation_iterator<
                            typename boost::range_iterator<Range>::type,
                            typename boost::range_iterator<Index>::type>;
    using base_t = boost::iterator_range<replaced_iterator>;
public:
    permutation_range(Range& r, Index& i)
            : base_t(replaced_iterator(boost::begin(r), boost::begin(i)),
                    replaced_iterator(boost::end(r), boost::end(i)))
    {}
};

template <typename Range, typename Index>
permutation_range<Range, Index>
permutation(Range& r, Index& i)
{
    return permutation_range<Range, Index>(r, i);
}

int main()
{
    std::vector<int> v1{99, 1, 99,  2, 99, 3};
    std::list<int> indexer{1, 3, 5};
    boost::copy(permutation(v1, indexer),
                std::ostream_iterator<int>(std::cout, " "));
}

输出

1 2 3

我想修改以上内容以使用 boost::joined_range .换句话说,取两个 vector ,然后将它们连接到 permutation_range 内的一个更长的范围内。这个想法很简单:

示例 将输出 2 4 6:

int main()
{
    std::vector<int> v1{1, 2, 3};
    std::vector<int> v2{4, 5, 6};
    std::list<int> indexer{1, 3, 5};
    boost::copy(permutation(v1, v2, indexer),
                std::ostream_iterator<int>(std::cout, " "));
}

到目前为止,我所有的尝试都以一大堆编译器错误而告终,我没有展示这些尝试,因为我可能离题太远了。我不知道这是否可能,但有人可以帮助我吗?

最终编辑(解决方案有一点技巧,可以在基类之前初始化范围)

#include <boost/range/join.hpp>
#include <boost/range/algorithm.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/iterator/permutation_iterator.hpp>
#include <vector>
#include <list>
#include <iterator>
#include <iostream>

template <typename R1, typename R2>
struct initialize_me_first
{
    initialize_me_first(typename boost::range::joined_range<const R1, const R2> j)
    : j_range(j)
    {}
    typename boost::range::joined_range<const R1, const R2> j_range;
};

template <typename Range1, typename Range2, typename Index>
class permutation_range :
        public initialize_me_first<Range1, Range2>,
        public boost::iterator_range<
                boost::permutation_iterator<
                        typename boost::range_iterator<
                            boost::range::joined_range<Range1, Range2>>::type,
                        typename boost::range_iterator<Index>::type>>
{
    using value_type = typename boost::range_value<Range1>::type;
    using replaced_iterator = boost::permutation_iterator<
                    typename boost::range_iterator<
                            boost::range::joined_range<Range1, Range2>>::type,
                            typename boost::range_iterator<Index>::type>;
    using base_t = boost::iterator_range<replaced_iterator>;
    using init = initialize_me_first<Range1, Range2>;
public:
    permutation_range(const Range1& r1, const Range2& r2, const Index& i)
            : init(boost::join(r1, r2)),
              base_t(replaced_iterator(boost::begin(init::j_range),
                                       boost::begin(i)),
                    replaced_iterator(boost::end(init::j_range),
                                       boost::end(i)))
    {}
};

template <typename Range1, typename Range2, typename Index>
permutation_range<const Range1, const Range2, const Index>
permutation(const Range1& r1, const Range2& r2, const Index& i)
{
    return permutation_range<const Range1,
                             const Range2,
                             const Index>(r1, r2, i);
}

int main()
{
    std::vector<int> v1{1, 2, 3};
    std::vector<int> v2{4, 5, 6};
    std::list<int> indexer{1, 3, 5};
    boost::copy(permutation(v1, v2, indexer),
                std::ostream_iterator<int>(std::cout, " "));
}

最佳答案

要连接两个范围,请使用 boost::join:

#include <boost/range/join.hpp>

boost::copy(permutation(boost::join(v1, v2), indexer), ...

但是将您的 Range 参数更改为通过 const 引用而不是非常量引用传递。没有理由要求这些参数的可修改版本,因为您实际上并没有改变它们的内容。

关于c++ - 如何使用 boost::joined_range 实现范围适配器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11639754/

相关文章:

c++ - std::bind 占位符的重载运算符

c++ - 如何使用 boost-range 在函数中封装自定义迭代器

c++ - boost 范围适配器变平

c++ - getline(cin,str) 的奇怪输出

c++ - 通过引用传递指向二维数组的指针

c++ - 排序 vector ,未在此范围内声明顺序(库?)

c++ - 在 for 循环和变量值中,此代码出现多个错误;

python - 在 ubuntu 16 上使用 python 3.5 安装 dlib——如何链接正确的 libboost .so 文件

c++ - 在 world.iprobe 上 boost MPI 崩溃

c++ - 将 std::pair 迭代器转换为 boost::iterator_range