2012-07-24 36 views
1

這裏是基於脫Implement a Range Adaptor with arguments一系列適配器的例子:如何實現與升壓的範圍適配器:: joined_range

#include <boost/range/join.hpp> 
#include <boost/range/algorithm.hpp> 
#include <boost/range/adaptors.hpp> 
#include <boost/range/iterator_range.hpp> 
#include <boost/iterator/permutation_iterator.hpp> 
#include <vector> 
#include <list> 
#include <iterator> 
#include <iostream> 

template <typename Range, typename Index> 
class permutation_range : 
     public boost::iterator_range< 
       boost::permutation_iterator< 
         typename boost::range_iterator<Range>::type, 
         typename boost::range_iterator<Index>::type>> 
{ 
    using value_type = typename boost::range_value<Range>::type; 
    using replaced_iterator = boost::permutation_iterator< 
          typename boost::range_iterator<Range>::type, 
          typename boost::range_iterator<Index>::type>; 
    using base_t = boost::iterator_range<replaced_iterator>; 
public: 
    permutation_range(Range& r, Index& i) 
      : base_t(replaced_iterator(boost::begin(r), boost::begin(i)), 
        replaced_iterator(boost::end(r), boost::end(i))) 
    {} 
}; 

template <typename Range, typename Index> 
permutation_range<Range, Index> 
permutation(Range& r, Index& i) 
{ 
    return permutation_range<Range, Index>(r, i); 
} 

int main() 
{ 
    std::vector<int> v1{99, 1, 99, 2, 99, 3}; 
    std::list<int> indexer{1, 3, 5}; 
    boost::copy(permutation(v1, indexer), 
       std::ostream_iterator<int>(std::cout, " ")); 
} 

輸出

我想適應以上使用boost::joined_range。換句話說,取兩個向量,然後將它們加入permutation_range內的一個較長範圍。這個想法很簡單:

這將輸出2 4 6

int main() 
{ 
    std::vector<int> v1{1, 2, 3}; 
    std::vector<int> v2{4, 5, 6}; 
    std::list<int> indexer{1, 3, 5}; 
    boost::copy(permutation(v1, v2, indexer), 
       std::ostream_iterator<int>(std::cout, " ")); 
} 

我所有的努力,到目前爲止已經在一個巨大的編譯器錯誤的列表結束後,我還沒有顯示嘗試,因爲我可能是離開。我不知道這是否可能,但有誰能幫我解決這個問題嗎?

最後編輯(方案一點點黑客得到的範圍內的基類初始化之前)

#include <boost/range/join.hpp> 
#include <boost/range/algorithm.hpp> 
#include <boost/range/adaptors.hpp> 
#include <boost/range/iterator_range.hpp> 
#include <boost/iterator/permutation_iterator.hpp> 
#include <vector> 
#include <list> 
#include <iterator> 
#include <iostream> 

template <typename R1, typename R2> 
struct initialize_me_first 
{ 
    initialize_me_first(typename boost::range::joined_range<const R1, const R2> j) 
    : j_range(j) 
    {} 
    typename boost::range::joined_range<const R1, const R2> j_range; 
}; 

template <typename Range1, typename Range2, typename Index> 
class permutation_range : 
     public initialize_me_first<Range1, Range2>, 
     public boost::iterator_range< 
       boost::permutation_iterator< 
         typename boost::range_iterator< 
          boost::range::joined_range<Range1, Range2>>::type, 
         typename boost::range_iterator<Index>::type>> 
{ 
    using value_type = typename boost::range_value<Range1>::type; 
    using replaced_iterator = boost::permutation_iterator< 
        typename boost::range_iterator< 
          boost::range::joined_range<Range1, Range2>>::type, 
          typename boost::range_iterator<Index>::type>; 
    using base_t = boost::iterator_range<replaced_iterator>; 
    using init = initialize_me_first<Range1, Range2>; 
public: 
    permutation_range(const Range1& r1, const Range2& r2, const Index& i) 
      : init(boost::join(r1, r2)), 
       base_t(replaced_iterator(boost::begin(init::j_range), 
             boost::begin(i)), 
        replaced_iterator(boost::end(init::j_range), 
             boost::end(i))) 
    {} 
}; 

template <typename Range1, typename Range2, typename Index> 
permutation_range<const Range1, const Range2, const Index> 
permutation(const Range1& r1, const Range2& r2, const Index& i) 
{ 
    return permutation_range<const Range1, 
          const Range2, 
          const Index>(r1, r2, i); 
} 

int main() 
{ 
    std::vector<int> v1{1, 2, 3}; 
    std::vector<int> v2{4, 5, 6}; 
    std::list<int> indexer{1, 3, 5}; 
    boost::copy(permutation(v1, v2, indexer), 
       std::ostream_iterator<int>(std::cout, " ")); 
} 

回答

2

要加入兩個範圍,使用boost::join

#include <boost/range/join.hpp> 

boost::copy(permutation(boost::join(v1, v2), indexer), ... 

但改變你的Range通過const引用而不是非const引用傳遞的參數。沒有理由要求這些參數的可修改版本,因爲您實際上並未對其內容進行排序。

+0

謝謝,我也意識到如果我想保留'permutation(v1,v2,indexer)'語法,我可以在'permutation'內部粘貼'boost :: join'。然而,我最初的目標是改變'permutation_range'使用'boost :: join'(不知道這是否可能)。 – 2012-07-24 22:13:10

+0

這會更困難。你的'permutation_range'需要有一個它創建的連接範圍的副本 - 它需要爲它創建的'replaced_iterator'對象傳遞相同的值'r'。在基類初始化之前,該範圍必須存在。這是可以解決的,但是你也會在參數列表的* middle *中出現一個有效的「可選」參數('v2')的語法複雜性。如果調用者想要加入範圍,請讓調用者對此負責,並保持界面簡單並專注於一件事情。 – 2012-07-24 22:21:09

+0

關於界面的好處,非常感謝您的幫助。在您的評論之後,我能夠想出一些東西(請參閱EDIT),但是,如何在基類初始化之前讓範圍存在? – 2012-07-24 23:13:23