2010-02-11 47 views
2

我想在頭文件中指定函數的輸入將是iterator_range,並且可以取消引用迭代器以獲得int。做這個的最好方式是什麼?我不想說iterator_range<std::vector<int>::iterator>,因爲這將綁定實施使用std::vector<int>頭文件中的iterator_range

希望任何想法指定功能的最佳途徑。

+0

這並不完全清楚,爲什麼你想綁定實現來使用boost :: iterator_range。通常,對於模板,類型是合適的,代碼編譯,或者不是,代碼編譯失敗。 – UncleBens 2010-02-11 16:35:38

+0

@UncleBens我沒有在我的頭文件中聲明模板,我只是想使用範圍。 – 2010-02-12 08:48:07

+1

基本上你是說你想使用'boost :: iterator_range '作爲參數,但不想使用模板?無法完成,國際海事組織。 – UncleBens 2010-02-12 16:19:53

回答

3

一種常見的方式做,這是使範圍內的模板參數,然後讓你做它的用法是「概念檢查」:

template<class SinglePassRange> 
void func(SinglePassRange const & nums) 
{ 
    typedef typename boost::range_iterator<SinglePassRange>::type It; 
    for(It it = nums.begin(), e = nums.end(); it != e; ++it) 
    { 
     int i = *it; 
     // Do something with your int 
    } 
} 

如果你確實範圍內這不會編譯不包含ints(或可轉換爲int的東西),所以不需要爲接口添加任何進一步的約束。但如果你真的願意,你可以在你的函數的開頭添加一個概念檢查(它將給您的客戶提供更好的錯誤信息):

BOOST_CONCEPT_ASSERT(
    (boost::Convertible<typename boost::range_value<SinglePassRange>::type, 
         int>)); 

最後,如果你不想讓你的函數模板那麼我認爲你將不得不採取boost::iterator_range<std::vector<int>::iterator>,但在這種情況下,我認爲沒有采取簡單的std::vector&方面的優勢。

+0

不回答我的問題,但確實有用的信息。 +1 – 2010-02-12 08:49:35

+1

謝謝。另外,你確定我的最後一句話不能回答你的問題嗎?我的意思是,一個否定的答案也是一個答案:) – Manuel 2010-02-12 08:59:47

+0

是的,我同意。感謝您的糾正。 – 2010-02-13 05:18:44

2

你的問題似乎有點不明確和/或要求是矛盾的。

看來你想要一個函數採取boost::iterator_range<Container<int>::iterator>其中容器可以是任何東西,但你不想要一個函數模板。

我不明白這是如何實現的,除了重載所有你想支持的迭代器的函數(如果你不嚴格意味着容器的內存容量爲int)。


這裏只是爲了好玩的東西,使用類型擦除,這樣確實是可以包裝任何迭代器(其提領操作將特定類型)快速any_iterator。 (實際上Google'ing你也許能找到一個更加完整的類具有相同的名稱。)

它是由一個非模板和功能的使用:

#include <numeric> 
#include <vector> 
#include <list> 
#include <iostream> 
#include <boost/iterator/iterator_facade.hpp> 
#include <boost/shared_ptr.hpp> 
#include <boost/range/iterator_range.hpp> 

namespace detail 
{ 
template <class T> 
class any_iterator_base 
{ 
public: 
    virtual ~any_iterator_base() {} 
    virtual void increment() = 0; 
    virtual bool equal(const any_iterator_base& other) const = 0; 
    virtual T& dereference() const = 0; 
}; 

template <class T, class Iter> 
class any_iterator_impl: public any_iterator_base<T> 
{ 
    Iter it; 
public: 
    any_iterator_impl(Iter it): it(it) {} 
    virtual void increment() { ++it; } 
    virtual bool equal(const any_iterator_base& other) const 
    { 
     //warning: throws if dynamic type of other is not the same as *this (can't compare iterators of different type) 
     return it == dynamic_cast<const any_iterator_impl<T, Iter>&>(other).it; 
    } 
    virtual T& dereference() const { return *it; } 
}; 

} //namespace detail 

template <class T> 
class any_iterator: public boost::iterator_facade<any_iterator<T>, T, boost::forward_traversal_tag> 
{ 
    boost::shared_ptr<detail::any_iterator_base<T> > iter; 
public: 
    template <class Iter> 
    any_iterator(Iter it): iter(new detail::any_iterator_impl<T, Iter>(it)) {} 
private: 
    friend class boost::iterator_core_access; 

    void increment() { iter->increment(); } 

    bool equal(const any_iterator& other) const 
    { 
     return iter->equal(*other.iter); 
    } 

    T& dereference() const { return iter->dereference(); } 
}; 

int sum(const boost::iterator_range<any_iterator<int> >& range) 
{ 
    return std::accumulate(range.begin(), range.end(), 0); 
} 

int main() 
{ 
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 
    std::vector<int> vec(arr, arr + 5); 
    std::list<int> li(arr + 5, arr + 10); 
    std::cout << sum(boost::make_iterator_range(any_iterator<int>(vec.begin()), any_iterator<int>(vec.end()))) << '\n'; 
    std::cout << sum(boost::make_iterator_range(any_iterator<int>(li.begin()), any_iterator<int>(li.end()))) << '\n'; 
    std::cout << sum(boost::make_iterator_range(any_iterator<int>(arr), any_iterator<int>(arr + 10))) << '\n'; 
} 

(我仍然懷疑,這是否是一個實際的解決方案。模板是爲了這些東西而製作的。)

+0

我現在明白你的意思了。你說得對,沒有功能模板就無法完成。 +1 – 2010-02-13 05:23:46