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

### 2069. Inconsistent exception spec for `basic_string` move constructor

Section: 21.3.3.3 [string.cons] Status: C++14 Submitter: Bo Persson Opened: 2011-07-01 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [string.cons].

View all issues with C++14 status.

Discussion:

Sub-clause 21.3.3.3 [string.cons] contains these constructors in paragraphs 2 and 3:

>     basic_string(const basic_string<charT,traits,Allocator>& str);
>     basic_string(basic_string<charT,traits,Allocator>&& str) noexcept;

> > […]

> > -3- Throws: The second form throws nothing if the allocator's move constructor throws nothing.

How can it ever throw anything if it is marked `noexcept`?

[2011-07-11: Daniel comments and suggests wording changes]

Further, according to paragraph 18 of the same sub-clause:

>     basic_string(const basic_string& str, const Allocator& alloc);
>     basic_string(basic_string&& str, const Allocator& alloc);

> > […]

> > -18- Throws: The second form throws nothing if `alloc == str.get_allocator()` unless the copy constructor for `Allocator` throws.

The constraint "unless the copy constructor for `Allocator` throws" is redundant, because according to Table 28 — Allocator requirements, the expressions

>     X a1(a);
>     X a(b);

impose the requirement: "Shall not exit via an exception".

[ 2011 Bloomington. ]

Move to Ready.

Proposed resolution:

This wording is relative to the FDIS.

1. Change 21.3.3.3 [string.cons] p3 as indicated (This move constructor has a wide contract and is therefore safely marked as `noexcept`):

   >     basic_string(const basic_string<charT,traits,Allocator>& str);
   >     basic_string(basic_string<charT,traits,Allocator>&& str) noexcept;

   > > -2- Effects: Constructs an object of class `basic_string` as indicated in Table 64. In the second form, `str` is left in a valid state with an unspecified value.

   > > -3- Throws: The second form throws nothing if the allocator's move constructor throws nothing.

2. Change 21.3.3.3 [string.cons] p18 as indicated (This move-like constructor may throw, if the allocators don't compare equal, but not because of a potentially throwing allocator copy constructor, only because the allocation attempt may fail and throw an exception):

   >     basic_string(const basic_string& str, const Allocator& alloc);
   >     basic_string(basic_string&& str, const Allocator& alloc);

   > > […]

   > > -18- Throws: The second form throws nothing if `alloc == str.get_allocator()` unless the copy constructor for `Allocator` throws.