This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Resolved status.

### 3111. Too strong precondition on `basic_string` constructor

Section: 21.3.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 21.3.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 21.3.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 range `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 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`.