2013-10-27 94 views
4

ISO C++ 11 24.3:爲什麼std :: next不接受InputIterator?

template <class InputIterator, class Distance> 
void advance(InputIterator& i, Distance n); 
// ... 
template <class ForwardIterator> 
ForwardIterator next 
(
    ForwardIterator x, 
    typename std::iterator_traits<ForwardIterator>::difference_type n = 1 
); 

爲什麼std::next不接受InputIterator S'

一個合法使用的情況下,我想的是:

first = find(next(first, x), last, 11); // ... 

我已經找到合適的DR

next/prev回報遞增的迭代器在不改變原有迭代器的值。但是,即使這可能會使InputIterator無效。需要ForwardIterator以保證'多次通過'的財產。

但我不明白multipass/invalidation是如何與此相關的。使用相同的多通道/無效的推理,我們甚至可以禁止std::findInputIterator S:

template<class InputIterator, class T> 
InputIterator find(InputIterator first, InputIterator last, const T& value); 

沒有什麼特別之處std::next在比較std::findstd::vector::insert(pos, first, last)具有完全合法的用例InputIterator小號

而且std::next(it, n)可用於通用代碼,該代碼不僅在InputIterator上運行。

+2

除了'std :: advance'來更準確地傳達InputIterators的語義。我們已經在聊天 – sehe

+2

這樣的代碼可以用於從'InputIterator'開始的所有迭代器上工作的泛型函數。我有興趣聽到客觀的原因。 –

+0

在另一個筆記上。根據C++ 11的特性,不應該對所有這些進行徹底檢查。也許像InputIterator這樣的東西應該是可移動的,而不是可複製的,以強調我們不能真的需要不同的迭代器到同一個來源? (但是,它應該全部用*範圍等等來整理出來,或許是一次大的改革。) –

回答

8

實際上,輸入迭代器不能被有效地複製,因爲一旦輸入迭代器遞增,任何留在左邊的副本都將失效。

std::next需要一個迭代器並返回已經被提前n次的另一個迭代器。你不能使用輸入迭代器來做到這一點,而不會使原始迭代器失效,這使得std::next毫無意義。通過對比,std::advance提前指定的迭代器n次,這對輸入迭代器來說很好。

std::nextoperator+(T*, size_t)的迭代器概括。 std::advanceoperator+=(T*&, size_t)的迭代器概括。很可能是std::advance,如operator+=,應該返回一個引用而不是void。

確實存在與std::find(及相關功能)類似的問題;他們也會使任何指定的輸入迭代器的副本無效。但委員會很可能認爲這個問題不太嚴重。

+0

'first = find(next(first,x),last,11);'is沒有意義,這是合法的用例。我不明白你爲什麼認爲'find'可以,但'next'不是 - 有同樣的失效。 –

+3

@evgeny:你可以自由使用'advance(first,x); first = find(first,last,11);'。也許「毫無意義」不是恰當的詞;我的意思是假裝有可能返回一個不同的迭代器是毫無意義的。 – rici

+0

我知道可以使用'advance'。對於更高級的迭代器類別,甚至可以使用'advance'而不是'next'。 「std :: next」是爲了方便起見而引入的。 「*你不能使用輸入迭代器來做到這一點,而不會使原始迭代器失效*」 - 同樣適用於'std :: find'。 –

相關問題