2013-08-28 68 views
7

C++ 11 không có vòng lặp dựa trên phạm vi cho chuỗi tích phân tầm xa.vòng lặp dựa trên dải C++ 11 cho phạm vi (L, R)

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

Vì vậy, tôi vừa quyết định mô phỏng nó.

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

Hỏi: Cách tổng quát phương pháp này cho bộ chuyển tiếp?

dụ:

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

Đó không phải là thực sự * khái quát * nó; số nguyên không phải là vòng lặp. Về cơ bản bạn đang tạo một hàm mới có cùng tên. –

Trả lời

6

Chuyên

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

thử nghiệm:

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

Bạn cũng có thể xóa phạm vi số nguyên dựa trên việc triển khai. Thay vào đó, hãy tạo một trình lặp số nguyên và chuyển nó tới trình thực hiện dãy dựa trên vòng lặp (giảm trùng lặp mã!). Một điều tôi thực hiện cá nhân của điều này là nó có điều kiện 'size' và' [] 'được định nghĩa nếu iterator là truy cập ngẫu nhiên, và iterator nguyên của tôi là truy cập ngẫu nhiên. – Yakk

1

Bạn đang cố gắng reimplement boost::iterator_rangeboost::counting_iterator. Đơn giản chỉ cần làm điều này thay vì:

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

Có thậm chí tồn tại một boost::counting_range đã: http://www.boost.org/doc/libs/1_47_0/libs/range/doc/html/range/reference/ranges/counting_range.html

+0

cho (auto e: temporaryObject {}); - đối với trường hợp này, điều gì có nghĩa là standart, tức là nó bảo đảm rằng thời gian cuộc sống tạm thời kết thúc sau vòng lặp hay không? –

+0

Tôi lấy đoạn này ra. Tôi đã từng nhầm lẫn. Xem tại đây: http://stackoverflow.com/questions/9657708/c11-the-range-based-for-statement-range-init-lifetime – Sebastian

+0

@KhurshidNormuradov có, nó chết. Ngữ nghĩa của phạm vi dựa trên vòng lặp là rõ ràng (bạn có thể triển khai mẫu google) và tuổi thọ của các đối tượng tạm thời được tạo trong suốt thời gian tồn tại (thời gian tồn tại tạm thời cho tham chiếu là thời gian tham chiếu). – Yakk