is_nothrow_constructible and destructors
Dave Abrahams

Created on 2011-12-09.00:00:00 last changed 12 months ago


Date: 2023-05-15.00:00:00

[ 2023-05-25; May 2023 mailing ]

Alisdair provided P2842R0.

Date: 2022-11-15.00:00:00

[ 2022-11-30; LWG telecon ]

Alisdair intends to write a paper for this.

Date: 2022-10-10.10:13:44

[ 2022-03; LWG reflector ]

A poll was taken to close the issue as NAD, with six votes in favour. (and one vote against, subsequently withdrawn).

"Write a paper if you want something else. These traits have well established meaning now." "Minimizing requirements is not as important a concern for standard library concepts as as minimizing the number of concepts. Requirements like 'I need to construct but not destroy an object' are niche enough that we don't need to support them."

Date: 2022-10-10.10:13:44

[ 2020-08; LWG reflector ]

A poll was taken to close the issue as NAD, but only gained three votes in favour (and one vote against, which was subsequently withdrawn).

Date: 2017-01-27.00:00:00

[ 2017-01-27 Telecon ]

Gave the issue a better title

This issue interacts with 2827

Ville would like "an evolution group" to take a look at this issue.

Date: 2018-10-11.01:45:28

[ 2012, Kona ]

Move to Open.

is_nothrow_constructible is defined in terms of is_constructible, which is defined by looking at a hypothetical variable and asking whether the variable definition is known not to throw exceptions. The issue claims that this also examines the type's destructor, given the context, and thus will return false if the destructor can potentially throw. At least one implementation (Howard's) does return false if the constructor is noexcept(true) and the destructor is noexcept(false). So that's not a strained interpretation. The issue is asking for this to be defined in terms of placement new, instead of in terms of a temporary object, to make it clearer that is_nothrow_constructible looks at the noexcept status of only the constructor, and not the destructor.

Sketch of what the wording would look like:

require is_constructible, and then also require that a placement new operation does not throw. (Remembering the title of this issue... What does this imply for swap?

If we accept this resolution, do we need any changes to swap?

STL argues: no, because you are already forbidden from passing anything with a throwing destructor to swap.

Dietmar argues: no, not true. Maybe statically the destructor can conceivably throw for some values, but maybe there are some values known not to throw. In that case, it's correct to pass those values to swap.

Date: 2011-12-09.00:00:00

IMO if we specified is_[nothrow_]constructible in terms of a variable declaration whose validity requires destructibility, it is clearly a bug in our specification and a failure to realize the actual original intent. The specification should have been in terms of placement-new.

At the time of the specification this was intended and the solution is not done by removing the destruction semantics of is_constructible.

The design of is_constructible was also impacted by the previous Constructible concept that explicitly contained destruction semantics, because during conceptification of the library it turned out to simplify the constraints in the library because you did not need to add Destructible all the time. It often was implied but never spoken out in C++03.

Pure construction semantics was considered as useful as well, so HasConstructor did also exist and would surely be useful as trait as well.

Another example that is often overlooked: This also affects wrapper types like pair, tuple, array that contain potentially more than one type: This is easy to understand if you think of T1 having a deleted destructor and T2 having a constructor that may throw: Obviously the compiler has potentially need to use the destructor of T1 in the constructor of std::pair<T1, T2> to ensure that the core language requirements are satisfied (All previous fully constructed sub-objects must be destructed).

The core language also honors this fact in [class.copy] p11:

A defaulted copy/move constructor for a class X is defined as deleted ([dcl.fct.def.delete]) if X has:
— any direct or virtual base class or non-static data member of a type with a destructor that is deleted or inaccessible from the defaulted constructor,

This is about is_nothrow_constructible in particular. The fact that it is foiled by not having a noexcept dtor is a defect.

Date User Action Args
2023-05-25 14:42:27adminsetmessages: + msg13582
2022-11-30 17:53:33adminsetmessages: + msg13130
2022-11-30 17:53:33adminsetstatus: nad -> open
2022-10-10 10:13:44adminsetmessages: + msg12846
2022-10-10 10:13:44adminsetmessages: + msg12845
2022-10-10 10:13:44adminsetstatus: open -> nad
2017-01-30 15:17:53adminsetmessages: + msg8796
2012-02-27 16:24:02adminsetmessages: + msg6033
2012-02-12 18:36:43adminsetstatus: new -> open
2011-12-09 00:00:00admincreate