2013-02-18 28 views
1

我想製作一個範圍,該範圍通過給定範圍的相鄰值進行轉換。 有沒有辦法做到這一點? 因此,我想要做一個在下面的代碼中描述的adjacent_transformed。升壓範圍適配器類似於可以訪問相鄰元素的轉換器

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()複製成本高昂,我該怎麼辦?

對不起,如果它不是一個相關的問題,但我沒有足夠的技能來理解升壓範圍的內部。

+0

有在Boost.Range沒有這樣的事情。 – Xeo 2013-02-18 08:05:39

回答

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

+2

這是非常危險的使用。只要忘記傳遞一個遞增的'v.begin()'或一個遞減的'v.end()',你就麻煩了。這也需要雙向範圍。一個更好的想法是'zipped_with'適配器,然後執行'v | zipped_with(next(v),next(v,2),fun)'。 (提示:Boost.Iterator的'zip_iterator'不能用於這個,因爲它吸引了最終的條件。) – Xeo 2013-02-18 08:14:29

+0

@Xeo,是的,它是危險的,沒有調整,膝蓋上寫着。 – ForEveR 2013-02-18 08:18:27

+0

@ForEveR對不起,回覆晚了。我檢查了你的代碼,它似乎工作。謝謝。它幫助我很多:) – Sungmin 2013-02-22 03:40:35