Method 3.2: Implement a Range Adaptor with arguments

| Home | Libraries | People | FAQ | More

##### Method 3.2: Implement a Range Adaptor with arguments

1. Provide a range for your return type, for example:

       #include <boost/range/adaptor/argument_fwd.hpp>
       #include <boost/range/iterator_range.hpp>
       #include <boost/iterator/transform_iterator.hpp>

       template<typename Value>
       class replace_value
       {
       public:
           typedef const Value& result_type;
           typedef const Value& argument_type;

           replace_value(const Value& from, const Value& to)
               : m_from(from), m_to(to)
           {
           }

           const Value& operator()(const Value& x) const
           {
               return (x == m_from) ? m_to : x;
           }
       private:
           Value m_from;
           Value m_to;
       };

       template<typename Range>
       class replace_range
       : public boost::iterator_range<
           boost::transform_iterator<
               replace_value<typename boost::range_value<Range>::type>,
               typename boost::range_iterator<Range>::type> >
       {
       private:
           typedef typename boost::range_value<Range>::type value_type;
           typedef typename boost::range_iterator<Range>::type iterator_base;
           typedef replace_value<value_type> Fn;
           typedef boost::transform_iterator<Fn, iterator_base> replaced_iterator;
           typedef boost::iterator_range<replaced_iterator> base_t;

       public:
           replace_range(Range& rng, value_type from, value_type to)
               : base_t(replaced_iterator(boost::begin(rng), Fn(from,to)),
                        replaced_iterator(boost::end(rng), Fn(from,to)))
            {
            }
        };

2. Implement a holder class to hold the arguments required to construct the RangeAdaptor. The holder combines multiple parameters into one that can be passed as the right operand of `operator|()`.

       template<typename T>
       class replace_holder : public boost::range_detail::holder2<T>
       {
       public:
           replace_holder(const T& from, const T& to)
               : boost::range_detail::holder2<T>(from, to)
           { }
       private:
           void operator=(const replace_holder&);
       };

3. Define an instance of the holder with the name of the adaptor

       static boost::range_detail::forwarder2<replace_holder>
       replaced = boost::range_detail::forwarder2<replace_holder>();

4. Define `operator|`

       template<typename SinglePassRange>
       inline replace_range<SinglePassRange>
       operator|(SinglePassRange& rng,
                 const replace_holder<typename boost::range_value<SinglePassRange>::type>& f)
       {
           return replace_range<SinglePassRange>(rng, f.val1, f.val2);
       }

       template<typename SinglePassRange>
       inline replace_range<const SinglePassRange>
       operator|(const SinglePassRange& rng,
                 const replace_holder<typename boost::range_value<SinglePassRange>::type>& f)
       {
           return replace_range<const SinglePassRange>(rng, f.val1, f.val2);
       }