boost::range库的自定义范围

Custom range for boost::range library

本文关键字:自定义 范围 range boost      更新时间:2023-10-16

我正在使用boost::range库编写过滤器和映射算法:

template <class Range> struct Converter
{
    Converter(const Range& p_range) : m_range(p_range) {}
    template<class OutContainer> operator OutContainer() const
    {
        return {m_range.begin(), m_range.end()};
    }
private:
    Range m_range;
};
template<class Range> Converter<Range> convert(const Range& p_range) { return {p_range}; }
template<class Range, class Fun> auto map(Range&& p_range, Fun&& p_fun)
{
    return convert(p_range | boost::adaptors::transformed(p_fun));
}
template<class Range, class Pred> auto filter(Range&& p_range, Pred&& p_pred)
{
    return convert(p_range | boost::adaptors::filtered(p_pred));
}

现在我可以这样使用它们:

std::vector<int> l_in  = {1, 2, 3, 4, 5};
std::vector<int> l_tmp_out = filter(l_in, [](int p){ return p < 4; });
std::vector<int> l_out = map(l_tmp_out, [](int p){ return p + 5; });

我也想这样写代码:

map(filter(l_in, [](int p){ return p < 4; }), [](int p){ return p + 5; });

不幸的是,我的Converter类没有与boost::range算法组合在一起,所以这个例子无法编译。我正在寻找一个合适的方法来改变这一点。

我跟随@sehe链接,结果证明我所要做的就是将这四行添加到Converter类中:

using iterator = typename Range::iterator;
using const_iterator = typename Range::const_iterator;
auto begin() const { return m_range.begin(); }
auto end() const { return m_range.end(); }

以下是我的看法:

Live On Coliru

#include <boost/range.hpp>
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include <iostream>
#include <vector>
namespace MyRange {
    template <typename R> struct Proxy {
        Proxy(R&& r)      : _r(std::move(r)) {}
        Proxy(R const& r) : _r(r) {}
        template <typename OutContainer> operator OutContainer() const {
            return boost::copy_range<OutContainer>(_r);
        }
        using iterator       = typename boost::range_mutable_iterator<R>::type;
        using const_iterator = typename boost::range_const_iterator<R>::type;
        auto begin() const { return range_begin(_r); }
        auto end()   const { return range_end(_r);   }
        auto begin()       { return range_begin(_r); }
        auto end()         { return range_end(_r);   }
      private:
        R _r;
    };
    template <typename R> auto make_proxy(R&& r) { return Proxy<R>(std::forward<R>(r)); }
    template <typename Range, typename Fun> auto map(Range&& p_range, Fun&& p_fun) {
        return make_proxy(std::forward<Range>(p_range) | boost::adaptors::transformed(std::forward<Fun>(p_fun)));
    }
    template <typename Range, typename Pred> auto filter(Range&& p_range, Pred&& p_pred) {
        return make_proxy(std::forward<Range>(p_range) | boost::adaptors::filtered(std::forward<Pred>(p_pred)));
    }
}
int main() {
    using namespace MyRange;
    {
        std::vector<int> l_in  = {1, 2, 3, 4, 5};
        std::vector<int> l_tmp_out = filter(l_in, [](int p){ return p < 4; });
        std::vector<int> l_out = map(l_tmp_out, [](int p){ return p + 5; });
        boost::copy(l_out, std::ostream_iterator<int>(std::cout << "nfirst:t", "; "));
    }
    {
        boost::copy(
                map(
                    filter(
                        std::vector<int> { 1,2,3,4,5 },
                        [](int p){ return p < 4; }),
                    [](int p){ return p + 5; }),
                std::ostream_iterator<int>(std::cout << "nsecond:t", "; "));
    }
}

打印

first:  6; 7; 8; 
second: 6; 7; 8; 
指出

  • 它更准确地使用std::forward<>
  • 使用const/非const迭代器
  • 它使用Boost Range特性(range_mutable_iterator<>等)而不是硬编码假设嵌套类型定义。这允许事物与其他范围(例如std::array<>甚至int (&)[])一起工作。

  • 用户自定义转换操作符出于类似的原因使用boost::copy_range<>