首页 > 解决方案 > 使用 boost::range 的相邻适配器

问题描述

我在问自己是否可以boost-range通过适配器进行扩展,我称之为adjacentAdaptor. 这个适配器基本上应该遍历 a 中的所有相邻元素对vectorlist依此类推。

我认为这个函数在我的用例中非常有用,我经常需要遍历表示时间步长的列表。

最后一个 for 循环的输出应该是这样的:

0 1
1 2
2 3

只有一个元素或没有元素的向量不应该产生任何结果。

我尝试使用boost::adaptors::sliced生成必要的子列表,但后来我不知道如何boost::range帮助我将两个子范围压缩到一个。

我刚刚找到了一个可能的解决方案boost::iterators,但我真的不喜欢必须编写的代码量。我也错过了firstsecond而是我不得不写一个笨拙的get<>. 不幸的是,如果向量为空,程序就会崩溃!

#include <vector>
#include <iostream>
#include <boost/range.hpp>
#include <boost/range/algorithm/transform.hpp>
#include <boost/range/adaptor/sliced.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/zip_iterator.hpp>

int main()
{
        std::vector<int> v = { 0,1,2,3 };
        for (auto iter : v | boost::adaptors::sliced(0, v.size() - 1)) {
            std::cout << "First: " << iter << std::endl;
        }
        for (auto iter : v | boost::adaptors::sliced(1, v.size())) {
            std::cout << "Second: "<< iter << std::endl;
        }
        auto s = boost::iterators::make_zip_iterator(boost::make_tuple(v.begin(), v.begin() + 1));
        auto e = boost::iterators::make_zip_iterator(boost::make_tuple(v.end()-1, v.end()));
        for (auto iter : boost::make_iterator_range(s, e)) {
            std::cout << iter.get<0>() << " " << iter.get<1>() << std::endl;
        }
//          for (auto iter : v | adjacentAdaptor) {
//              std::cout << iter.first << " " << iter.second << std::endl;
//          }
}

我很高兴能在这个问题上得到任何帮助。

自己的部分解决方案

经过一些模板类型的推断,我想出了一些相对有用的东西。

#include <vector>
#include <iostream>
#include <boost/range.hpp>
#include <boost/range/algorithm/transform.hpp>
#include <boost/range/adaptor/sliced.hpp>
#include <boost/iterator.hpp>
#include <boost/iterator/zip_iterator.hpp>

template<typename T>
using retHelperType = decltype(boost::iterators::make_zip_iterator(boost::make_tuple(T().begin(), T().begin() + 1)));

template<typename T>
using retType = decltype(boost::make_iterator_range(retHelperType<T>(), retHelperType<T>()));

template<typename T>
retType<T> adjacentIterator(T& v) {
    if (v.empty()) {
        auto s = boost::iterators::make_zip_iterator(boost::make_tuple(v.end(), v.end()));
        auto e = boost::iterators::make_zip_iterator(boost::make_tuple(v.end(), v.end()));
        return boost::make_iterator_range(s, e);
    }
    else {
        auto s = boost::iterators::make_zip_iterator(boost::make_tuple(v.begin(), std::next(v.begin())));
        auto e = boost::iterators::make_zip_iterator(boost::make_tuple(std::prev(v.end()), v.end()));
        return boost::make_iterator_range(s, e);
    }
}

int main()
{
    retType<std::vector<int>> x;
    std::vector<int> v = { };

    for (auto iter : adjacentIterator(v)) {
        std::cout << iter.get<0>() << " " << iter.get<1>() << std::endl;
    }
}

first不过,使用and访问元素会更好second,但我不知道如何实现这种行为。

标签: c++stliteratorboost-rangeboost-iterators

解决方案


推荐阅读