【问题标题】:boost range adaptor similar to transformed which can access adjacent elements升压范围适配器类似于 transform 可以访问相邻元素
【发布时间】:2013-02-18 06:10:02
【问题描述】:

我想创建一个由给定范围的相邻值转换的范围。 有没有办法做到这一点? 因此,我想制作一个相邻的转换,如下面的代码中所述。

class Func{
public:
    typedef int result_type;

    int operator()(int a, int b, int c) {
        return a+b+c;        
    }

};

int main(){
    vector<int> v{1,1,1,1,1};
    auto rng = make_iterator_range( next(v.begin(), prev(v.end()) ) | adjacent_transformed( Func() );
    // rng shoud be {3, 3, 3}
}

另一个快速问题:将Func() 的右值传递给范围适配器boost::adaptors::transformed 是否安全?据我测试,它按预期工作。如果安全,是否将 Func() 复制到 transformed 中?那么Func()复制成本高怎么办?

对不起,如果这不是一个相关的问题,但我不够熟练,无法理解提升范围的内部结构。

【问题讨论】:

  • Boost.Range 中没有这样的东西。

标签: c++ boost c++11 boost-range


【解决方案1】:

你可以使用这样的东西。我认为应该对其进行调整,但它确实有效。

template<typename Iterator, typename Functor>
class iterator : public boost::iterator_adaptor<
                 iterator<Iterator, Functor>,
                 Iterator,
                 typename std::iterator_traits<Iterator>::value_type,
                 boost::forward_traversal_tag,
                 typename std::iterator_traits<Iterator>::value_type,
                 typename std::iterator_traits<Iterator>::difference_type
            >, private Functor
{
   typedef boost::iterator_adaptor<
                 iterator<Iterator, Functor>,
                 Iterator,
                 typename std::iterator_traits<Iterator>::value_type,
                 boost::forward_traversal_tag,
                 typename std::iterator_traits<Iterator>::value_type,
                 typename std::iterator_traits<Iterator>::difference_type
            > base_t;
public:
   friend class boost::iterator_core_access;

   iterator(Iterator current, Functor fnc):
      base_t(current),
      Functor(fnc)
   {
   }

   typename std::iterator_traits<Iterator>::value_type dereference() const
   {
      Iterator i = this->base();
      const Functor& fnc = *this;
      return fnc(*boost::prior(i), *i, *boost::next(i));
   }
};

template<typename Iter, typename Func>
iterator<Iter, Func> make_iterator(Iter i, Func f)
{
   return iterator<Iter, Func>(i, f);
}

template<typename F, typename R>
struct trans_range : public boost::iterator_range<
                     iterator<typename boost::range_iterator<R>::type,
                     F>>
{
   typedef boost::iterator_range<
                     iterator<typename boost::range_iterator<R>::type,
                     F>> base_t;
   trans_range(F f, R& r) :
      base_t(make_iterator(boost::begin(r), f), make_iterator(boost::end(r), f))
   {
   }
};

template< class T >
struct holder
{
   T val;
   holder( T t ) : val(t)
   { }
};

template<typename T>
struct trans_holder : holder<T>
{
   trans_holder(T r) : holder<T>(r) { }
};

template< template<class> class Holder >
struct forwarder
{
   template< class T >
   Holder<T> operator()( T t ) const
   {
       return Holder<T>(t);
   }
};

template<typename R, typename F>
inline trans_range<F, R> operator |(R range, const trans_holder<F>& f)
{
   return trans_range<F, R>(f.val, range);
}

forwarder<trans_holder> transformed = forwarder<trans_holder>();

example

【讨论】:

  • 使用起来非常危险。只要忘记传递递增的v.begin() 或递减的v.end(),你就有麻烦了。这也需要双向范围。一个更好的主意是使用zipped_with 适配器,然后使用v | zipped_with(next(v), next(v, 2), fun)。 (提示:Boost.Iterator 的 zip_iterator 对此不起作用,因为它在结束条件方面很糟糕。)
  • @Xeo,是的,这是危险的,没有调整,写在膝盖上。
  • @ForEveR 抱歉回复晚了。我检查了你的代码,它似乎工作。谢谢。它对我有很大帮助:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-11-14
  • 2013-01-24
  • 2017-11-30
  • 1970-01-01
  • 2021-11-24
  • 2023-04-05
  • 2023-03-07
相关资源
最近更新 更多