头文件中的iterator_range

时间:2010-02-11 14:54:46

标签: c++ boost

我想在头文件中指定函数的输入是iterator_range,并且可以取消引用迭代器以获得int。做这个的最好方式是什么?我不想说iterator_range<std::vector<int>::iterator>因为这会将实现绑定到使用std::vector<int>

非常感谢任何想法以最佳方式指定功能。

2 个答案:

答案 0 :(得分: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
   } 
}

如果您的范围不包含整数(或可转换为int的东西),则无法编译,因此无需向界面添加任何进一步的约束。但是,如果您真的想要,可以在功能开始时添加概念检查(它将为您的客户提供更好的错误消息):

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

最后,如果你不想让你的功能成为一个模板,那么我认为你必须应对boost::iterator_range<std::vector<int>::iterator>,但在这种情况下,我认为采取一个简单的{{ {1}}。

答案 1 :(得分:2)

你的问题似乎有点不清楚和/或要求是矛盾的。

似乎你想要一个函数来取boost::iterator_range<Container<int>::iterator>,其中Container可以是任何东西,但你不需要函数模板。

我没有看到如何实现这一点,除非为你想要支持的所有迭代器重载函数(如果你不严格意味着 int 的容器,那就更糟了)


这是一个有趣的东西,一个使用类型擦除的快速any_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';
}

(我仍然怀疑,这是否是一个实用的解决方案。模板是为这些东西制作的。)