簡體   English   中英

容器的迭代器能否產生左值以外的東西?

[英]Can a container's iterator yield something other than an lvalue?

我或多或少得出的結論是,不可能編寫一個其value_type沒有直接存儲在容器中的合格容器。 我認為這很不幸,因為我經常希望我有一些容器,其中值的類型要么是部分計算的,要么是由不連續的部分組成的(以下示例,但與問題不直接相關)。 我知道如何編寫使用代理對象的迭代器,盡管這很煩人。 但是我現在想知道C ++標准中是否確實有此類野獸的空間。 這里的雜語太多了; tl; dr版本很簡單:§24.2.5的第1段和第6段真正意味着什么,違反明顯含義的程度將破壞標准算法? 或者,換句話說,如何解釋它們以允許代理迭代器?

正如Pete Becker指出的那樣,實際上沒有什么可迫使我的容器符合對標准庫容器提出的要求。 但是,為了使用具有許多標准算法的容器,它必須具有至少帶有forward_iterator_tag的一致迭代器,或者必須基於該迭代器,但仍要設法滿足特定算法對其施加的操作(如果不是形式上的)要求迭代器。

這是我的理由:

表96(第23.2.1節),容器要求,包括:

Expression     Return type         Assertion/note
------------   -------------       ---------------------
X::iterator    iterator type       any iterator category
               whose value         that meets the
               type is T           forward iterator
                                   requirements.
                                   Convertible to
                                   const_iterator.

 a.begin()     iterator;
               const_iterator for
               constant a.

現在,轉發迭代器:

第24.2.5節,第 1:

如果……,則類或指針類型X滿足正向迭代器的要求。

—如果X是一個可變迭代器,則reference是對T的引用; 如果X是const迭代器,則reference是對const T的引用

確實沒有直接要求*a返回reference (其中aX類型)的要求。 要求是:

表107中的表(輸入迭代器) *a如果a是不可引用的,則a必須“可轉換為T”。

來自表106(迭代器)中的*r必須具有類型reference ,其中rX&類型X&並且是可取消引用的。

但是,表106還指定++r返回X& ,因此*++r必須是reference 此外,(按照表107), *a++必須是reference ,盡管(表109) a[n]僅需要“可轉換為參考”。 我得說,我看不出*a ,其中a是類型的X*r其中, r是類型的X&可能是不同的,但也許我錯過了一些微妙。

也許這里有個小擺動間,但不多。 在某個時候,如果容器中實際上沒有T ,則需要准備創建T ,以便您可以提供對其的引用。

但關鍵是

第24.2.5節,第 6( ab是類型X值):如果ab都是可引用的,則當且僅當*a*b綁定到同一對象時, a == b

我找不到bound to的正式定義,但在我看來,制作不可尋址對象的迭代器的通常策略是創建一個代理對象,通常將其存儲在迭代器本身內。 在這種情況下,除了禁止兩個不同迭代器對象之間的相等比較成功外,即使它們在邏輯上指示相同的位置,也需要對“綁定到”以任何方式解釋24.2.5 / 6的含義有非常寬泛的理解。在容器中。

另一方面,我注意到應該知道的DietmarKühl在回答這個問題時說:

C ++ 2011放寬了要求,並不一定需要使用迭代器才能產生左值

那么,迭代器可以返回代理嗎? 如果可以的話,這種代理的性質是什么? 我的推理這樣的迭代器不合格的原因在哪里失敗?


如所承諾的,一些有效value_types不會連續存儲在容器中的容器:

1)一個緊湊的關聯容器,其鍵和值類型可以更有效地存儲在兩個單獨的向量中。 (將鍵保留在向量中還可以提高緩存友好性,並減少分配開銷。)

2)偽裝為map<integer_type, T>vector<T> ,簡化了與其他map<X, T>類型的互操作性。

3)通過壓縮其他幾個容器而形成的邏輯容器,產生一個邏輯value_type,它是對壓縮容器的值類型的引用的tuple (在某些應用程序中,一個或多個壓縮容器可以根據其他值或序列號進行整體計算。)

4)聚合類型的容器的視圖,其中僅包含某些值。 (很可能底層容器和視圖都是元組,其中視圖元組的類型列表是底層容器類型的子集,可能以不同的順序排列)。

我確信其他人可以輕松地添加到此列表中; 這些只是過去幾個月來我以某種方式入侵的工具。

不要通過考慮“合格的容器”來限制自己:標准中沒有什么依賴於一個容器。 將容器要求視為描述標准中定義的容器要求的簡捷方式。 而已。 只要您的容器產生的迭代器是有效的,您就可以使用所有相應的算法,也可以使用您自己編寫的算法。

最好的模型是std::vector< bool > 它盡可能接近合規性,但其迭代器確實會產生代理。

該標准甚至指定std::vector<bool>::reference是一個類。 但是容器要求表指定X::reference產生“ T的左值”。 因此,它是嚴格不合規的。

但是迭代器並不綁定到T 迭代器的value_type必須為Treference輸入迭代器的要求, reference必須轉換為value_type

正如皮特·貝克爾(Pete Becker)所提到的那樣,需求表涵蓋了相當廣泛的范圍,並且各個算法指定了它們的需求。 只有需要reference才能真正成為引用的算法才會中斷,這只是顯而易見的一種。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM