Document number: N3150=10-0140
Date: 2010-10-14
Author:J. Daniel Garcia
Project: Programming Language C++, Library Working Group
Reply to: josedaniel.garcia@uc3m.es
N3150 - Removing non-empty dynamic exception specifications from the library
During the Rapperswil meeting the Library Working Group decided to remove dynamic excepion specifications from the library, as this is a
deprecated feature now.
This is mostly done by N3114. However, N3114 handles only empty dynamic exception specifications. The only place in the standard library where
non-empty dynamic expection specifications are used is in some versions of operator new, which may throw std::bad_alloc. This
paper corrects this, making them noexcept(false).
This paper presents proposed wording for this change.
The paper partially addresses National Body comments CH 16 and GB 60.
Discussion
There are two points in the library where a non-empty dynamic exception specification is used:
- void* operator new(std::size_t)
- void* operator new[](std::size_t)
For both of them the dynamic exception specification may be removed, making those operators noexcept(false) (they may throw).
One could argue that then some clarification could be needed fo the exception which is thrown.
However, for the first one, this is already done by 18.6.1.1/3, stating that bad_alloc may be thrown:
Required behavior: Return a non-null pointer to suitably aligned storage (3.7.4), or else throw a
bad_alloc exception. This requirement is binding on a replacement version of this function.
For the second one, this is implicit in 18.6.1.2/3:
Required behavior: Same as for operator new(std::size_t). This requirement is binding on a
replacement version of this function.
Note that this is a way of implicitly stating that operator new[](std::size_t) may throw a std::bad_alloc.
Identified changes
All changes in this paper are against N3126.
This paper proposes the following changes:
- Remove throw(std::bad_alloc) from operator new(std::size_t) and operator new[](std::size_t).
- Clarify that std::bad_alloc does not need to be implicitly introduced.
Acknoledgments
Daniel Krügler reviewed this paper and provided helful feedback.
Wording
3.7.4 Dynamic storage duration
After p. 2
void* operator new(std::size_t) throw(std::bad_alloc);
void* operator new[](std::size_t) throw(std::bad_alloc);
...
These implicit declarations introduce only the function names operator new, operator new[], operator
delete, operator delete[]. [ Note: the implicit declarations do not introduce the names std, std::bad_-
alloc, and std::size_t, or any other names that the library uses to declare these names. Thus, a newexpression,
delete-expression or function call that refers to one of these functions without including the
header <new> is well-formed. However, referring to std, std::bad_alloc, and std::size_t is ill-formed
unless the name has been declared by including the appropriate header. —end note ] Allocation and/or
deallocation functions can also be declared and defined for any class (12.5).
18.6 Dynamic memory management
After p. 1
...
void* operator new(std::size_t size) throw(std::bad_alloc);
...
void* operator new[](std::size_t size) throw(std::bad_alloc);
...
18.6.1.1 Single-object forms
Before p. 1
void* operator new(std::size_t size) throw(std::bad_alloc);
18.6.1.2 Array forms
Before p. 1
void* operator new[](std::size_t size) throw(std::bad_alloc);