2013-08-28 192 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