const and non-const variablesSection: 23.2.2 [container.requirements.general] Status: C++23 Submitter: Jonathan Wakely Opened: 2017-10-17 Last modified: 2023-11-22
Priority: 3
View other active issues in [container.requirements.general].
View all other issues in [container.requirements.general].
View all issues with C++23 status.
Discussion:
[container.requirements.general] p4 says:
In Tables 83, 84, and 85
Xdenotes a container class containing objects of typeT,aandbdenote values of typeX,udenotes an identifier,rdenotes a non-constvalue of typeX, andrvdenotes a non-constrvalue of typeX.
This doesn't say anything about whether a and b are allowed to be
const, or must be non-const. In fact Table 83 uses them
inconsistently, e.g. the rows for "a = rv" and "a.swap(b)" most
certainly require them to be non-const, but all other uses are valid
for either const or non-const X.
[2017-11 Albuquerque Wednesday night issues processing]
Priority set to 3; Jonathan to provide updated wording.
Wording needs adjustment - could use "possibly const values of type X"
Will distinguish between lvalue/rvalue
Previous resolution [SUPERSEDED]:
This wording is relative to N4687.
Change 23.2.2 [container.requirements.general] p4 as indicated:
-4- In Tables 83, 84, and 85
Xdenotes a container class containing objects of typeT,aandbdenote values of typeX,udenotes an identifier,rand s denotes anon-constvalues of typeX, andrvdenotes a non-constrvalue of typeX.Change 23.2.2 [container.requirements.general], Table 83 "Container requirements", as indicated:
Table 83 — Container requirements Expression Return type Operational
semanticsAssertion/note
pre/post-conditionComplexity […]ar = rvX&All existing elements
ofare either movear
assigned to or
destroyedshall be equal toar
the value thatrvhad
before this
assignmentlinear […]ar.swap(bs)voidexchanges the
contents ofandarbs(Note A) […]swap(ar,bs)voidar.swap(bs)(Note A)
[2020-05-03; Daniel provides alternative wording]
Previous resolution [SUPERSEDED]:
This wording is relative to N4861.
Change 23.2.2 [container.requirements.general] as indicated:
[Drafting note:
The following presentation also transforms the current list into a bullet list as we already have in 23.2.8 [unord.req] p11
It has been decided to replace the symbol
rbys, because it is easy to confuse withrvbut means an lvalue instead, and the other container tables use it rarely and for something completely different (iterator value)A separate symbol
vis introduced to unambigiously distinguish the counterpart of a non-constrvalue (See 16.4.4.2 [utility.arg.requirements])Two separate symbols
bandcrepresent now "(possiblyconst) values, while the existing symbolarepresents an unspecified value, whose meaning becomes defined when context is provided, e.g. for overloads likebegin()andend-4- In Tables 73, 74, and 75:
(4.1) —
Xdenotes a container class containing objects of typeT,(4.2) —
aanddenotes a valuebsof typeX,(4.2) —
bandcdenote (possiblyconst) values of typeX,(4.3) —
iandjdenote values of type (possiblyconst)X::iterator,(4.4) —
udenotes an identifier,(?.?) —
vdenotes an lvalue of type (possiblyconst)Xor an rvalue of typeconst X,(4.5) —
rsandtdenotes anon-constvaluelvalues of typeX, and(4.6) —
rvdenotes a non-constrvalue of typeX.Change 23.2.2 [container.requirements.general], Table 73 "Container requirements" [tab:container.req], as indicated:
[Drafting note: The following presentation also moves the copy-assignment expression just before the move-assignment expression]
Table 73: — Container requirements [tab:container.req] Expression Return type Operational
semanticsAssertion/note
pre/post-conditionComplexity […]X(av)Preconditions: Tis Cpp17CopyInsertable
intoX(see below).
Postconditions:.av == X(av)linear X u(av);
X u =av;Preconditions: Tis Cpp17CopyInsertable
intoX(see below).
Postconditions:u ==.avlinear X u(rv);
X u = rv;Postconditions: uis equal to the value
thatrvhad before this construction(Note B) t = vX&Postconditions: t == v.linear at = rvX&All existing elements
ofare either moveat
assigned to or
destroyedshall be equal toat
the value thatrvhad
before this
assignmentlinear […]ac == bconvertible to bool==is an equivalence relation.
equal(ac.begin(),
ac.end(),
b.begin(),
b.end())Preconditions: Tmeets the
Cpp17EqualityComparable requirementsConstant if ,ac.size() != b.size()
linear otherwiseac != bconvertible to boolEquivalent to !(ac == b)linear at.swap(bs)voidexchanges the
contents ofandatbs(Note A) swap(at,bs)voidat.swap(bs)(Note A) r = aX&Postconditions:r == a.linearac.size()size_typedistance(ac.begin(),ac.end())constant ac.max_size()size_typedistance(begin(), end())for the largest
possible containerconstant ac.empty()convertible to boolac.begin() ==ac.end()constant
[2022-04-20; Jonathan rebases the wording on the latest draft]
[2022-09-05; Reflector poll]
Set status to Tentatively Ready after five votes in favour during reflector poll in April 2022.
[2022-11-12 Approved at November 2022 meeting in Kona. Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4910.
Change 23.2.2 [container.requirements.general] as indicated:
[Drafting note:
It has been decided to replace the symbol
rbys, because it is easy to confuse withrvbut means an lvalue instead, and the other container tables use it rarely and for something completely different (iterator value)A separate symbol
vis introduced to unambigiously distinguish the counterpart of a non-constrvalue (See 16.4.4.2 [utility.arg.requirements])Two separate symbols
bandcrepresent now "(possiblyconst) values, while the existing symbolarepresents an unspecified value, whose meaning becomes defined when context is provided, e.g. for overloads likebegin()andend
-1- In subclause [container.gen.reqmts],
(1.1) —
Xdenotes a container class containing objects of typeT,(1.2) —
aanddenotes a value of typebdenote valuesX,(?.?) —
bandcdenote values of type (possiblyconst)X,(1.3) —
iandjdenote values of type (possiblyconst)X::iterator,(1.4) —
udenotes an identifier,(?.?) —
vdenotes an lvalue of type (possiblyconst)Xor an rvalue of typeconst X,(1.5) —
rdenotes asandtdenote non-constvaluelvalues of typeX, and(1.6) —
rvdenotes a non-constrvalue of typeX.
Change 23.2.2.2 [container.reqmts] as indicated:
[Drafting note: The following presentation also moves the copy-assignment expression just before the move-assignment expression]
X u(av); X u =av;-12- Preconditions:
Tis Cpp17CopyInsertable intoX(see below).-13- Postconditions:
u ==.av-14- Complexity: Linear.
X u(rv); X u = rv;-15- Postconditions:
uis equal to the value thatrvhad before this construction.-14- Complexity: Linear for
arrayand constant for all other standard containers.t = v-?- Result:
X&.-?- Postconditions:
t == v.-?- Complexity: Linear.
at = rv-17- Result:
X&.-18- Effects: All existing elements of
are either move assigned to or destroyed.at-19- Postconditions:
shall be equal to the value thatatrvhad before this assignment.-20- Complexity: Linear.
[…]
ab.begin()-24- Result:
iterator;const_iteratorfor constantab.-25- Returns: An iterator referring to the first element in the container.
-26- Complexity: Constant.
ab.end()-27- Result:
iterator;const_iteratorfor constantab.-28- Returns: An iterator which is the past-the-end value for the container.
-29- Complexity: Constant.
ab.cbegin()-30- Result:
const_iterator.-31- Returns:
const_cast<X const&>(ab).begin()-32- Complexity: Constant.
ab.cend()-33- Result:
const_iterator.-34- Returns:
const_cast<X const&>(ab).end()-35- Complexity: Constant.
[…]
ac == b-39- Preconditions:
Tmeets the Cpp17EqualityComparable requirements.-40- Result: Convertible to
bool.-41- Returns:
equal(.ac.begin(),ac.end(), b.begin(), b.end())[Note 1: The algorithm
equalis defined in 26.6.13 [alg.equal]. — end note]-42- Complexity: Constant if
, linear otherwise.ac.size() != b.size()-43- Remarks:
==is an equivalence relation.ac != b-44- Effects: Equivalent to
!(.ac == b)at.swap(bs)-45- Result:
void.-46- Effects: Exchanges the contents of
andat.bs-47- Complexity: Linear for
arrayand constant for all other standard containers.swap(at,bs)-48- Effects: Equivalent to
at.swap(bs)r = a
-49- Result:X&.
-50- Postconditions:r == a.
-51- Complexity: Linear.ac.size()-52- Result:
size_type.-53- Returns:
distance(, i.e. the number of elements in the container.ac.begin(),ac.end())-54- Complexity: Constant.
-55- Remarks: The number of elements is defined by the rules of constructors, inserts, and erases.
ac.max_size()-56- Result:
size_type.-57- Returns:
distance(begin(), end())for the largest possible container.-58- Complexity: Constant.
ac.empty()-59- Result: Convertible to
bool.-60- Returns:
ac.begin() ==ac.end())-61- Complexity: Constant.
-62- Remarks: If the container is empty, then
isac.empty()true.