2195. Missing constructors for match_results

Section: 28.6.9 [re.results] Status: C++23 Submitter: Daniel Krügler Opened: 2012-10-06 Last modified: 2023-11-22

Priority: 3

View all other issues in [re.results].

View all issues with C++23 status.

Discussion:

The requirement expressed in 28.6.9 [re.results] p2

The class template match_results shall satisfy the requirements of an allocator-aware container and of a sequence container, as specified in 23.2.4 [sequence.reqmts], except that only operations defined for const-qualified sequence containers are supported.

can be read to require the existence of the described constructors from as well, but they do not exist in the synopsis.

The missing sequence constructors are:

match_results(initializer_list<value_type>);
match_results(size_type, const value_type&);
template<class InputIterator> match_results(InputIterator, InputIterator);

The missing allocator-aware container constructors are:

match_results(const match_results&, const Allocator&);
match_results(match_results&&, const Allocator&);

It should be clarified, whether (a) constructors are an exception of above mentioned operations or (b) whether at least some of them (like those accepting a match_results value and an allocator) should be added.

As visible in several places of the standard (including the core language), constructors seem usually to be considered as "operations" and they certainly can be invoked for const-qualified objects.

The below given proposed resolution applies only the minimum necessary fix, i.e. it excludes constructors from above requirement.

[2013-04-20, Bristol]

Check current implementations to see what they do and, possibly, write a paper.

[2013-09 Chicago]

Ask Daniel to update the proposed wording to include the allocator copy and move constructors.

[2014-01-18 Daniel changes proposed resolution]

Previous resolution from Daniel [SUPERSEDED]:

  1. Change 28.6.9 [re.results] p2 as indicated:

    The class template match_results shall satisfy the requirements of an allocator-aware container and of a sequence container, as specified in 23.2.4 [sequence.reqmts], except that only operations defined for const-qualified sequence containers that are not constructors are supported.

[2015-05-06 Lenexa]

MC passes important knowledge to EF.

VV, RP: Looks good.

TK: Second form should be conditionally noexcept

JY: Sequence constructors are not here, but mentioned in the issue writeup. Why?

TK: That would have been fixed by the superseded wording.

JW: How does this interact with Mike Spertus' allocator-aware regexes? [...] Perhaps it doesn't.

JW: Can't create match_results, want both old and new resolution.

JY: It's problematic that users can't create these, but not this issue.

VV: Why conditional noexcept?

MC: Allocator move might throw.

JW: Update superseded wording to "only non-constructor operations that are"?

MC: Only keep superseded, but append "and the means of constructing match_results are limited to [...]"?

JY: Bullet 4 paragraph 2 needs to address the allocator constructor.

Assigned to JW for drafting.

[2015-10, Kona Saturday afternoon]

STL: I want Mike Spertus to be aware of this issue.

Previous resolution from Daniel [SUPERSEDED]:

This wording is relative to N3936.

  1. Change 28.6.9 [re.results] p4, class template match_results synopsis, as indicated:

    […]
    // 28.10.1, construct/copy/destroy:
    explicit match_results(const Allocator& a = Allocator());
    match_results(const match_results& m);
    match_results(const match_results& m, const Allocator& a);
    match_results(match_results&& m) noexcept;
    match_results(match_results&& m, const Allocator& a) noexcept;
    […]
    
  2. Change 28.6.9.2 [re.results.const] as indicated: [Drafting note: Paragraph 6 as currently written, makes not much sense, because the noexcept does not allow any exception to propagate. Further-on, the allocator requirements do not allow for throwing move constructors. Deleting it seems to be near to editorial — end drafting note]

    match_results(const match_results& m);
    match_results(const match_results& m, const Allocator& a);
    

    -4- Effects: Constructs an object of class match_results, as a copy of m.

    match_results(match_results&& m) noexcept;
    match_results(match_results&& m, const Allocator& a) noexcept;
    

    -5- Effects: Move-constructs an object of class match_results from m satisfying the same postconditions as Table 142. AdditionallyFor the first form, the stored Allocator value is move constructed from m.get_allocator().

    -6- Throws: Nothing if the allocator's move constructor throws nothing.

[2019-03-27 Jonathan updates proposed resolution]

Previous resolution [SUPERSEDED]:

This wording is relative to N4810.

These edits overlap with the proposed resolution of 2191 but it should be obvious how to resolve the conflicts. Both resolutions remove the word "Additionally" from p4. Issue 2191 removes the entire Throws: element in p5 but this issue replaces it with different text that applies to the new constructor only.

  1. Change 28.6.9 [re.results] p4, class template match_results synopsis, as indicated:

    […]
    // 30.10.1, construct/copy/destroy:
    explicit match_results(const Allocator& a = Allocator());
    match_results(const match_results& m);
    match_results(const match_results& m, const Allocator& a);
    match_results(match_results&& m) noexcept;
    match_results(match_results&& m, const Allocator& a);
    […]
    
  2. Change 28.6.9.2 [re.results.const] as indicated:

    match_results(const match_results& m);
    match_results(const match_results& m, const Allocator& a);
    

    -3- Effects: Constructs an object of class match_results, as a copy of m. For the second form, the stored Allocator value is constructed from a.

    match_results(match_results&& m) noexcept;
    match_results(match_results&& m, const Allocator& a);
    

    -4- Effects: Move-constructs an object of class match_results from m satisfying the same postconditions as Table 128. AdditionallyFor the first form, the stored Allocator value is move constructed from m.get_allocator(). For the second form, the stored Allocator value is constructed from a.

    -6- Throws: Nothing. The second form throws nothing if a == m.get_allocator().

[2022-11-06; Daniel syncs wording with recent working draft]

To ensure that all constructors are consistent in regard to the information about how the stored allocator is constructed, more wording is added. This harmonizes with the way how we specify the individual container constructors (Such as vector) even though 23.2.2.5 [container.alloc.reqmts] already provides some guarantees. For the copy-constructor we intentionally refer to 23.2.2.2 [container.reqmts] so that we don't need to repeat what is said there.

[Kona 2022-11-08; Move to Ready]

[2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Voting → WP.]

Proposed resolution:

This wording is relative to N4917.

  1. Change 28.6.9 [re.results], class template match_results synopsis, as indicated:

    […]
    // 28.6.9.2 [re.results.const], construct/copy/destroy:
    match_results() : match_results(Allocator()) {}
    explicit match_results(const Allocator& a);
    match_results(const match_results& m);
    match_results(const match_results& m, const Allocator& a);
    match_results(match_results&& m) noexcept;
    match_results(match_results&& m, const Allocator& a);
    […]
    
  2. Change 28.6.9.2 [re.results.const] as indicated:

    explicit match_results(const Allocator& a);
    

    -?- Effects: The stored Allocator value is constructed from a.

    -2- Postconditions: ready() returns false. size() returns 0.

    match_results(const match_results& m);
    match_results(const match_results& m, const Allocator& a);
    

    -?- Effects: For the first form, the stored Allocator value is obtained as specified in 23.2.2.2 [container.reqmts]. For the second form, the stored Allocator value is constructed from a.

    -3- Postconditions: As specified in Table 142 [tab:re.results.const].

    match_results(match_results&& m) noexcept;
    match_results(match_results&& m, const Allocator& a);
    

    -4- Effects: For the first form, tThe stored Allocator value is move constructed from m.get_allocator(). For the second form, the stored Allocator value is constructed from a.

    -5- Postconditions: As specified in Table 142 [tab:re.results.const].

    -?- Throws: The second form throws nothing if a == m.get_allocator() is true.