代码之家  ›  专栏  ›  技术社区  ›  amit kumar

头文件中的迭代器范围

  •  2
  • amit kumar  · 技术社区  · 15 年前

    我想在头文件中指定函数的输入是 iterator_range int . 最好的方法是什么?我不想说 iterator_range<std::vector<int>::iterator> 因为这绑定了要使用的实现 std::vector<int> .

    2 回复  |  直到 15 年前
        1
  •  3
  •   Manuel    15 年前

    一种常见的方法是将范围设为模板参数,然后将其用作“概念检查”:

    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
       } 
    }
    

    如果您的范围不包含int(或可转换为int的内容),则不会编译,因此无需向接口添加任何进一步的约束。但是如果您真的需要,可以在函数的开头添加一个概念检查(它将为您的客户机提供更好的错误消息):

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

    boost::iterator_range<std::vector<int>::iterator> 但在这种情况下,我认为采取简单的 std::vector& .

        2
  •  2
  •   UncleBens    15 年前

    您的问题似乎有点不清楚和/或要求相互矛盾。

    boost::iterator_range<Container<int>::iterator> 容器可以是任何东西,但您不需要函数模板。

    我看不出这是如何实现的,除了为所有您想要支持的迭代器重载函数(如果您不是严格意义上的 内景


    它由非模板求和函数使用:

    #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';
    }
    

    (我仍然怀疑,这是否是一个切实可行的解决办法。模板是为这些东西制作的。)