2012-08-09 17 views
5

mỗi người (xuất sắc) câu hỏi C++ OutputIterator post-increment requirements, chúng ta quan sát rằng đối với một giá trị dereferenceable và incrementable r của OutputIterator loại X, và giá trị so o của loại thích hợp, khái niệmdereference gán để một OutputIterator gấp đôi tăng lên

*r++ = o; 

là hợp lệ và có ngữ nghĩa tương đương với

X a(r); 
++r; 
*a = o; 

Tuy nhiên, là nó vẫn là trường hợp a là dereference-chuyển nhượng nếu r đã được tăng lên nhiều lần trong giai đoạn can thiệp; có nghĩa là, mã này có hợp lệ không?

X a(r); 
++r; 
++r; 
*a = o; 

Rất khó để xem cách hoạt động trên giá trị có thể ảnh hưởng đến tính hợp lệ của các hoạt động trên một giá trị khác, nhưng ví dụ: InputIterator (24.2.3) đã, dưới sự postconditions của ++r:

Bất kỳ bản sao của giá trị trước đó của r không còn cần thiết hoặc được dereferenceable hoặc là trong lĩnh vực ==.

phần liên quan: 24.2.2 Iterator, 24.2.4 Output lặp, 17.6.3.1 yêu cầu lập luận Template.

Ngoài ra, nếu đây là không yêu cầu phải có giá trị, được có bất kỳ tình huống mà khai thác không hiệu lực của nó sẽ hỗ trợ trong việc thực hiện (hiệu quả w.r.t., đơn giản) của một loại OutputIterator trong khi vẫn quan sát các yêu cầu hiện hành?

+1

SGI STL (http://www.sgi.com/tech/stl/OutputIterator.html chú thích cuối trang 3) rõ ràng cấm hành vi này, buộc một chuỗi gia số xen kẽ và các chuyển nhượng dereference; tuy nhiên, tôi không thể lấy được yêu cầu đó từ tiêu chuẩn C++. Có '* chỉ một lần *' trong [24.2.4: 2] có nghĩa là chính xác một lần hoặc nhiều nhất một lần? – nknight

+0

Câu trả lời này: (http://stackoverflow.com/a/4004035/985943) làm cho tôi nghĩ rằng hành vi này là hợp lệ cho một 'ostream_iterator', mà chỉ thực sự tăng trên nhiệm vụ, bỏ qua các hoạt động tăng khác. Tuy nhiên, có vẻ như tất cả các OutputIterator đều phải tuân theo các ngữ nghĩa đó. – nknight

+0

@nknight rất thú vị. * chỉ một lần * xuất hiện 5 lần trong tiêu chuẩn, tại 3,4: 1 với một ý nghĩa khác nhau, và tại 5,17: 7, 12,8: 15, 29,6,5: 8 theo nghĩa * nhiều nhất một lần (nhưng thường một lần) *. * chính xác một lần * và * nhiều nhất một lần * mỗi lần xuất hiện 5 lần. Chắc chắn nếu tiêu chuẩn dành cho các hạn chế của SGI, họ sẽ kết hợp ngôn ngữ đó? – ecatmur

Trả lời

2

Vấn đề này được nêu ra vào năm 2004 là defect 485 và từ ngữ trong n3066 làm rõ vấn đề, yêu cầu bộ lặp đầu ra chỉ cần hỗ trợ một chuỗi gia số xen kẽ và chuyển nhượng/gán. Vì vậy, trong ví dụ của bạn, r không cần gia tăng sau ++r đầu tiên, trừ khi có một sự can thiệp/chuyển nhượng can thiệp. Hành vi này cũng được yêu cầu bởi số STL của SGI (xem chú thích 3). Như bạn đã đề cập ở trên, n3225 xuất hiện mà không có các bản sửa lỗi từ n3066, vì vậy defect 2035 được nâng lên; tuy nhiên, bản sửa lỗi đã không được đưa vào phiên bản đã xuất bản của C++ 11 (ISO/IEC 14882: 2011).

Bên cạnh đó, khiếm khuyết 2035 nói rằng a (từ X a(r++);) không thể được sử dụng như *a = 0:

"Sau khi hoạt động này [tức là, ++r] r là không bắt buộc phải incrementable và bất kỳ bản có giá trị trước trong số r không còn cần thiết để có thể đăng ký hoặc tăng thêm. "

Có những trường hợp điều này có thể hỗ trợ việc triển khai (theo đơn đơn giản): xem ví dụ:this question trên ostream_iterator, trong đó số tăng gấp đôi (không hợp lệ) này bị bỏ qua chỉ đơn giản là trả lại *this; chỉ có một dereference/assignment gây ra ostream_iterator để thực sự tăng lên.