2182. Container::[const_]reference types are misleadingly specified

Section: 23.2.2 [container.requirements.general] Status: C++14 Submitter: Daniel Krügler Opened: 2012-08-20 Last modified: 2017-07-05

Priority: 0

View other active issues in [container.requirements.general].

View all other issues in [container.requirements.general].

View all issues with C++14 status.

Discussion:

According to Table 96 (Container requirements) the return type of X::reference and X::const_reference is "lvalue of T" and "const lvalue of T", respectively. This does not make much sense, because an lvalue is an expression category, not a type. It could also refer to an expression that has a type, but this doesn't make sense either in this context, because obviously X::[const_]reference are intended to refer to types.

Given the fact that vector<bool> has no real reference type for X::[const_]reference and this definition presumably is intended to cover such situations as well, one might think that the wording is just a sloppy form of "type that represents a [const] lvalue of T". But this is also problematic, because basically all proxy reference expressions are rvalues.

It is unclear what the intention is. A straightward way of fixing this wording could make X::[const_]reference identical to [const] T&. This holds for all Library containers except for vector<bool>.

Another way of solving this definition problem would be to impose a requirement that holds for both references and reference-like proxies. Both X::reference and X::const_reference would need to be convertible to const T&. Additionally X::reference would need to support for a mutable container an assignment expression of the form declval<X::reference>() = declval<T>() (this presentation intentionally does not require declval<X::reference&>() = declval<T>()).

Further, the Table 96 does not impose any relations between X::reference and X::const_reference. It seems that at least X::reference needs to be convertible to X::const_reference.

A related question is whether X::reference is supposed to be a mutable reference-like type, irrespective of whether the container is an immutable container or not. The way, type match_results defines reference identical to const_reference indicates one specific interpretation (similarly, the initializer_list template also defines member type reference equal to const value_type&). Note that this can be a different decision as that for iterator and const_iterator, e.g. for sets the type X::reference still is a mutable reference, even though iterator is described as constant iterator.

The proposed resolution is incomplete in regard to the last question.

[2013-03-15 Issues Teleconference]

Moved to Review.

Alisdair notes that this looks like wording in the right direction. Wonders about congruence of these typedefs and the similar ones for iterators.

[2013-09 Chicago]

Moved to Ready.

Consensus that the requirements should require real references, just like iterators, as containers are required to support at least ForwardIterators, which have the same restriction on references.

Matt will file a new issue for some additional concerns with regex match_results.

[2014-02-10, Daniel comments]

The new issue opened by Matt is LWG 2306.

[Issaquah 2014-02-11: Move to Immediate]

Issue should have been Ready in pre-meeting mailing.

Proposed resolution:

This wording is relative to N3376.

  1. Change Table 96 — "Container requirements" as indicated:

    Table 96 — Container requirements
    Expression Return type Operational
    Semantics
    Assertion/note
    pre-/post-condition
    Complexity
    X::reference lvalue of T&   compile time
    X::const_reference const lvalue ofconst T&   compile time