2012-07-19 52 views
6

Có một thuật toán giống như std::copy chấp nhận bốn trình vòng lặp hay không, biểu thị hai phạm vi?Thuật toán giống như sao chép với bốn vòng lặp

Về cơ bản, nó nên dừng sao chép càng sớm càng theo phạm vi được kiệt sức:

template<typename Iter> 
void copy_range(Iter begin1, Iter end1, Iter begin2, Iter end2) 
{ 
    for (; (begin1 != end1) && (begin2 != end2); ++begin1, ++begin2) 
    { 
     *begin2 = *begin1; 
    } 
} 
+2

Bạn vừa tạo một tài khoản. Câu hỏi của bạn là gì? –

+0

Có lẽ bạn có thể sử dụng hàm C++ 11 ['std :: copy_if'] (http://en.cppreference.com/w/cpp/algorithm/copy)? –

+0

có thể là phiên bản hack của 'partial_sort_copy'? mặc dù tôi thẳng thắn không thấy điểm làm phức tạp nó ... – Nim

Trả lời

10

Không không có những điều như vậy thật đáng buồn. Điều gần nhất là std::copy_n.

Và tất nhiên thuật toán bạn vừa viết.

Tùy thuộc vào loại iterator sử dụng (ngẫu nhiên hay không), sử dụng này là hiệu quả hơn (vì chỉ có một kiểm tra cần phải được thực hiện cho mỗi lần lặp) so với thuật toán của bạn:

std::copy_n(begin1, 
      std::min(std::distance(begin1, end1), std::distance(begin2, end2)), 
      begin2); 

Một thay thế là một iterator đầu ra kiểm tra, một cái gì đó dọc theo dòng này (phác thảo thô, không kiểm tra code):

template<class Iter> 
class CheckedOutputIter { 
public: 
    // exception used for breaking loops 
    class Sentinel { } 

    CheckedOutputIter() 
     : begin(), end() { } 

    CheckedOutputIter(Iter begin, Iter end) 
     : begin(begin), end(end) { } 

    CheckedOutputIter& operator++() { 
     // increment pas end? 
     if (begin == end) { 
      throw Sentinel(); 
     } 

     ++begin; 
     return *this; 
    } 

    CheckedOutputIter operator++(int) { 
     // increment past end? 
     if (begin == end) { 
      throw Sentinel(); 
     } 

     CheckedOutputIter tmp(*this); 

     ++begin; 

     return tmp; 
    } 

    typename iterator_traits<Iter>::value_type operator*() { 
     return *begin; 
    } 


private: 
    Iter begin, end; 
}; 

Cách sử dụng:

try { 
    std::copy(begin1, end1, CheckedOutputIter(begin2, end2)); 
} catch(const CheckedOutputIter::Sentinel&) { } 

Điều này có hiệu suất tương tự như giải pháp của bạn, nhưng nó có thể sử dụng rộng rãi hơn.

Các vấn đề liên quan