[英]Why can an rvalue not bind to a non-const lvalue reference, other than the fact that writing to a temporary has no effect?
[英]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
(其中a
為X
類型)的要求。 要求是:
表107中的表(輸入迭代器)
*a
如果a
是不可引用的,則a
必須“可轉換為T”。來自表106(迭代器)中的
*r
必須具有類型reference
,其中r
為X&
類型X&
並且是可取消引用的。
但是,表106還指定++r
返回X&
,因此*++r
必須是reference
。 此外,(按照表107), *a++
必須是reference
,盡管(表109) a[n]
僅需要“可轉換為參考”。 我得說,我看不出*a
,其中a
是類型的X
和*r
其中, r
是類型的X&
可能是不同的,但也許我錯過了一些微妙。
也許這里有個小擺動間,但不多。 在某個時候,如果容器中實際上沒有T
,則需要准備創建T
,以便您可以提供對其的引用。
但關鍵是
第24.2.5節,第 6(
a
和b
是類型X
值):如果a
和b
都是可引用的,則當且僅當*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
必須為T
並reference
輸入迭代器的要求, reference
必須轉換為value_type
。
正如皮特·貝克爾(Pete Becker)所提到的那樣,需求表涵蓋了相當廣泛的范圍,並且各個算法指定了它們的需求。 只有需要reference
才能真正成為引用的算法才會中斷,這只是顯而易見的一種。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.