2015-11-07 45 views
14

對於std::begin,我們有一個容器兩個重載:std :: begin和end的const重載的目的是什麼?

template< class C > 
auto begin(C& c) -> decltype(c.begin()); 
template< class C > 
auto begin(const C& c) -> decltype(c.begin()); 

C常量性可以通過平時的模板演繹規則來推斷,因此它似乎是第二個重載是多餘的。我錯過了什麼?

回答

9

在rvalue上調用begin(和end)是合理的,只要我們在容器被銷燬後不使用生成的迭代器。但是,將右值傳遞給形式爲T&的參數將不起作用,這是第二次超載發揮作用的地方。

但是,它可能是,我們正在處理的前range-based for proposal wording一個輕率的改造:

添加以下的[container.concepts.member]結束:

template<Container C> concept_map Range<C> { 
    typedef C::iterator iterator; 
    iterator begin(C& c) { return Container<C>::begin(c); } 
    iterator end(C& c) { return Container<C>::end(c); } }; 

template<Container C> concept_map Range<const C> { 
    typedef C::const_iterator iterator; 
    iterator begin(const C& c) { return Container<C>::begin(c); } 
    iterator end(const C& c) { return Container<C>::end(c); } }; 

當清楚概念不會變成C++ 11時,論文被修改了,並且所有四個函數temploids可能被翻譯成等價的命名空間s應付功能模板。這會導致rvalues被接受(可能是非預期的)後果,而原始代碼只是爲了區分不同限定的容器類型。

請注意,現代實現的begin/end將使用轉發引用 - 例如,

template <typename T> 
constexpr auto begin(T&& t) 
    -> decltype(std::forward<T>(t).begin()) { 
    return std::forward<T>(t).begin(); 
} 
+1

我並不確信這是故意設計。從容器中獲取'begin()'而不能從同一個容器中獲得'end()'看起來並不有用。 –

+0

@ T.C。 ......除非你知道它的長度的上限。無論如何,我試圖追查這篇論文。 – Columbo

+2

當然,除了數組rvalues沒有重載,它的長度實際上是在類型中,所以在調用站點中肯定是已知的。就我個人而言,我懷疑它是適應舊的[容器概念圖]的一件神器(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2778.htm#container-concept- maps-container-concepts-member),它們分別使用'const_iterator'和'iterator'分別具有'const'和'nonconcon'版本。 –

相關問題