3111. Too strong precondition on basic_string constructor

Section: 27.4.3.3 [string.cons] Status: Resolved Submitter: Andrzej Krzemienski Opened: 2018-05-09 Last modified: 2020-09-06

Priority: 2

View all other issues in [string.cons].

View all issues with Resolved status.

Discussion:

The following is the spec for basic_string constructor taking a pointer and a size in N4741 ([string.cons]/12-14):

basic_string(const charT* s, size_type n, const Allocator& a = Allocator());

(12) Requires: s points to an array of at least n elements of charT.

(13) Effects: Constructs an object of class basic_string and determines its initial string value from the array of charT of length n whose first element is designated by s.

(14) Postconditions: data() points at the first element of an allocated copy of the array whose first element is pointed at by s, size() is equal to n, and capacity() is a value at least as large as size().

This implies that passing a null pointer and a zero size to this constructor is violating the precondition, as null pointer cannot be described as "pointing to an array of at least n elements of charT". On the other hand, being able to pass {nullptr, 0} is essential for basic_string to be able to inter-operate with other containers that are allowed to use the null pointer value to represent sequences of size zero:

std::vector<char> v{};
assert(v.data() == nullptr); // on some implementations
std::string s(v.data(), v.size()); // nullptr on some implementations

This has been already acknowledged as a defect in issue 2235 and applied, but the resolution still implies a too strong precondition.

Previous resolution [SUPERSEDED]:

This wording is relative to N4741.

  1. Edit 27.4.3.3 [string.cons] as indicated:

    basic_string(const charT* s, size_type n, const Allocator& a = Allocator());
    

    -12- Requires: Unless n == 0, s points to an array of at least n elements of charT.

    -13- Effects: Constructs an object of class basic_string and, unless n == 0, determines its initial string value from the array of charT of length n whose first element is designated by s.

    -14- Postconditions: If n != 0, then data() points at the first element of an allocated copy of the array whose first element is pointed at by s,; size() is equal to n, and capacity() is a value at least as large as size().

[2016-06-04 Marshall provides alternate resolution]

[2018-06-18 after reflector discussion]

Priority set to 2

[2018-08 mailing list discussion]

This will be resolved by Tim's string rework paper.

Resolved by the adoption of P1148 in San Diego.

Proposed resolution:

This wording is relative to N4750.

  1. Edit 27.4.3.3 [string.cons] as indicated:

    basic_string(const charT* s, size_type n, const Allocator& a = Allocator());
    

    -12- Requires: [s, s + n) is a valid ranges points to an array of at least n elements of charT.

    -13- Effects: Constructs an object of class basic_string and determines its initial string value from the range [s, s + n)array of charT of length n whose first element is designated by s.

    -14- Postconditions: data() points at the first element of an allocated copy of the array whose first element is pointed at by s, size() is equal to n, and capacity() is a value at least as large as size(), and traits::compare(data(), s, n) == 0.