2013-08-28 69 views
7

C++ 11对于距离积分序列没有基于范围的循环。基于范围的循环C++ 11用于范围(L,R)

for(auto e : {0..10}) // wouldn't compile!!! 

所以我只是决定模拟它。

template< class T , bool enable = std::is_integral<T>::value > 
struct range_impl 
{ 
    struct iterator 
    { 
     constexpr T operator *()const noexcept { return value; } 
     iterator& operator ++()noexcept { ++value; return *this; } 

     friend 
     constexpr bool operator != (const iterator & lhs, const iterator rhs) noexcept 
     { 
      return lhs.value != rhs.value; 
     } 
     T value; 
    }; 

    constexpr iterator begin()const noexcept { return { first }; } 
    constexpr iterator end ()const noexcept { return { last }; } 

    T first; 
    T last ; 
}; 




template< class T > 
range_impl<T> range(T first , T last) noexcept 
{ 
    return {first, last}; 
} 

int main(){ 
    // print numbers in [ 0..10), i.e. 0 1 2 3 4 5 6 7 8 9 
    for(auto e : range(0,10)) std::cout << e << ' '; 
    std::cout << std::endl; 
} 

问:如何为ForwardIterators推广此方法?

例如:

template< class ForwardIterator, class T > 
bool find(ForwardIterator first, ForwardIterator last, T const& value) 
{ 
    for(auto e: range(first, last)) if (e == v) return true; 
    return false; 
} 
+3

那不是真的*以偏概全*它;整数不是迭代器。你基本上是用同一个名字创建一个新的函数。 –

回答

6

专业化

template< class Iterator> 
struct range_impl<Iterator, false> 
{ 
    range_impl(Iterator first, Iterator last) 
    : first(first), last(last) 
    {} 

    constexpr Iterator begin()const noexcept { return { first }; } 
    constexpr Iterator end ()const noexcept { return { last }; } 

    Iterator first; 
    Iterator last ; 
}; 

测试

int main(){ 
    for(auto e : range(0,10)) std::cout << e << ' '; 
    std::cout << std::endl; 
    const char* a[] = { "Say", "hello", "to", "the", "world" }; 
    for(auto e : range(a, a + 5)) std::cout << e << ' '; 
    std::cout << std::endl; 
} 
+0

您也可以删除基于整数的范围实现。相反,创建一个整数迭代器,并将其传递给基于迭代器的范围实现(减少代码重复!)。我个人实现这个的另一件事是,如果迭代器是随机访问,并且我的整数迭代器是随机访问,那么它有条件地定义了size和'[]'。 (auto e:temporaryObject {}); – Yakk

1

您正在试图重新实现boost::iterator_rangeboost::counting_iterator。只要做到这一点,而不是:

template< class T > 
boost::iterator_range< boost::counting_iterator<T> > range(T const& tBegin, T const& tEnd) { 
    return boost::iterator_range< boost::counting_iterator<T> >(tBegin, tEnd); 
} 

甚至有存在boost::counting_range已经:http://www.boost.org/doc/libs/1_47_0/libs/range/doc/html/range/reference/ranges/counting_range.html

+0

; - 对于这种情况,说什么standart,即它保证临时对象的生命周期在循环之后结束? –

+0

我把这段话写出来了。我有一部分错了。看到这里:http://stackoverflow.com/questions/9657708/c11-the-range-based-for-statement-range-init-lifetime – Sebastian

+0

@KhurshidNormuradov是的,它死了。基于范围的for循环的语义是明确的(你可以谷歌示例实现),以及在其中创建的临时对象的生命周期(临时绑定到引用的生命周期是引用的生命周期)。 – Yakk