2016-09-28 29 views
2

方法std::basic_string::substr具有參數pos, count,指定位置[pos,pos + count + 1)中元素的邏輯範圍。相反,大部分的標準庫函數(例如,std::for_each)具有參數,某種形式的類似於begin, end的,指定範圍[開始,結束)爲什麼std :: basic_string :: substr不遵循[begin,end]約定?

這似乎是一個例外,那麼,混淆一些(見問題here,here,herehere)。爲什麼這裏不使用慣常的範圍約定?還請注意std::vector::erase,另一種隨機存取容器的方法,確實按照慣例約定

+2

通過使用控制器可以獲得相同的行爲。例如。 'std :: string substring {text.begin(),text.end()}'。不知道爲什麼'substr'沒有這樣的過載。 – Zereges

+0

@Zereges:因爲它是多餘的。如果你有兩個迭代器表示子字符串,爲什麼把它們傳遞給'std :: string :: substr()'重載,如果你也可以將它們傳遞給'std :: string :: string()'。 – MSalters

+0

@MSalters在STL中有很多冗餘重載甚至函數。 STL的設計並非簡約。 – Zereges

回答

5

歷史原因。標準庫有多個來源,其中之一是STL。它帶來了begin,end公約。 std::string早於STL合併到標準庫中,並且有大量現有代碼使用.substr(pos,length)

+0

...我想如果我們現在正在設計庫,'std :: string'看起來會非常不同。 –

5

一個簡單的猜測:

不同的方法,你舉有不同的行爲,這可能是爲什麼一些使用迭代器和其他沒有。

std::for_each是通用的 - 有一個通用版本的方法在任何容器(甚至原始數組)上工作的最簡單方法是使用迭代器。

std::vector::eraseSequenceContainer概念的一部分,所以它必須有「通用」的形式,可以在任何類型的容器的工作(你可以使用一個std::vectorposcount,但對於一個std::list?還是std::set? )。有了這樣的概念是非常有用的創建通用代碼:

template <typename C> 
void real_remove(C &c, const typename C::value_type &value) { 
    c.erase(std::remove(c.begin(), c.end(), value), c.end()); 
} 

這隻能是因爲std::...::erase爲任何SequenceContainer明確界定。

在另一方面,std::basic_string::substrstd::basic_string只有一部分(不像erase這是std::liststd::vector一部分,...),並返回一個std::basic_string (不迭代器,你會用一個迭代器在這裏做?)。

,我們在std::basic_string其他「非通用」(即,不屬於由一些概念強制的)的方法,通常是整個家庭的find方法,insert具有size_typeappend,等等上的過載。

在一個主觀的看法,我認爲這是最好有一個std::basic_string不表現得像其他容器,因爲它不是(我不知道的是,標準要求std::basic_string是一個SequenceContainer或任何類似的)。

,因爲你想要一個新的std::basic_string這裏不能返回迭代器,所以你將有一個方法採取迭代器返回,但一個對象......我會覺得這更令人不安的比有pos/count,而不是first/last

1

我不能說爲什麼,我不在場,但對於你錯過了[開始,結束)約定範圍內的構造。

template< class InputIt > 
basic_string(InputIt first, InputIt last, 
       const Allocator& alloc = Allocator()); 
相關問題