Skip to content

Commit aeece2c

Browse files
committed
[except.spec] Exception specifications are function declarators
1 parent 88b2b8d commit aeece2c

File tree

2 files changed

+266
-266
lines changed

2 files changed

+266
-266
lines changed

source/declarations.tex

Lines changed: 266 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4109,6 +4109,272 @@
41094109
\end{footnote}
41104110
\indextext{declarator!function|)}
41114111

4112+
\rSec2[except.spec]{Exception specifications}%
4113+
\indextext{exception specification|(}
4114+
4115+
\pnum
4116+
The predicate indicating whether a function cannot exit via an exception
4117+
is called the \defn{exception specification} of the function.
4118+
If the predicate is false,
4119+
the function has a
4120+
\indextext{exception specification!potentially-throwing}%
4121+
\defnx{potentially-throwing exception specification}%
4122+
{potentially-throwing!exception specification},
4123+
otherwise it has a
4124+
\indextext{exception specification!non-throwing}%
4125+
\defn{non-throwing exception specification}.
4126+
The exception specification is either defined implicitly,
4127+
or defined explicitly
4128+
by using a \grammarterm{noexcept-specifier}
4129+
as a suffix of a function declarator\iref{dcl.fct}.
4130+
4131+
\begin{bnf}
4132+
\nontermdef{noexcept-specifier}\br
4133+
\keyword{noexcept} \terminal{(} constant-expression \terminal{)}\br
4134+
\keyword{noexcept}\br
4135+
\end{bnf}
4136+
4137+
\pnum
4138+
\indextext{exception specification!noexcept!constant expression and}%
4139+
In a \grammarterm{noexcept-specifier}, the \grammarterm{constant-expression},
4140+
if supplied, shall be a contextually converted constant expression
4141+
of type \keyword{bool}\iref{expr.const};
4142+
that constant expression is the exception specification of
4143+
the function type in which the \grammarterm{noexcept-specifier} appears.
4144+
A \tcode{(} token that follows \keyword{noexcept} is part of the
4145+
\grammarterm{noexcept-specifier} and does not commence an
4146+
initializer\iref{dcl.init}.
4147+
The \grammarterm{noexcept-specifier} \keyword{noexcept}
4148+
without a \grammarterm{constant-expression}
4149+
is
4150+
equivalent to the \grammarterm{noexcept-specifier}
4151+
\tcode{\keyword{noexcept}(\keyword{true})}.
4152+
\begin{example}
4153+
\begin{codeblock}
4154+
void f() noexcept(sizeof(char[2])); // error: narrowing conversion of value 2 to type \keyword{bool}
4155+
void g() noexcept(sizeof(char)); // OK, conversion of value 1 to type \keyword{bool} is non-narrowing
4156+
\end{codeblock}
4157+
\end{example}
4158+
4159+
\pnum
4160+
If a declaration of a function
4161+
does not have a \grammarterm{noexcept-specifier},
4162+
the declaration has a potentially throwing exception specification
4163+
unless it is a destructor or a deallocation function
4164+
or is defaulted on its first declaration,
4165+
in which cases the exception specification
4166+
is as specified below
4167+
and no other declaration for that function
4168+
shall have a \grammarterm{noexcept-specifier}.
4169+
In an explicit instantiation\iref{temp.explicit}
4170+
a \grammarterm{noexcept-specifier} may be specified,
4171+
but is not required.
4172+
If a \grammarterm{noexcept-specifier} is specified
4173+
in an explicit instantiation,
4174+
the exception specification shall be the same as
4175+
the exception specification of all other declarations of that function.
4176+
A diagnostic is required only if the
4177+
exception specifications are not the same
4178+
within a single translation unit.
4179+
4180+
\pnum
4181+
\indextext{exception specification!virtual function and}%
4182+
If a virtual function has a
4183+
non-throwing exception specification,
4184+
all declarations, including the definition, of any function
4185+
that overrides that virtual function in any derived class
4186+
shall have a non-throwing
4187+
exception specification,
4188+
unless the overriding function is defined as deleted.
4189+
\begin{example}
4190+
\begin{codeblock}
4191+
struct B {
4192+
virtual void f() noexcept;
4193+
virtual void g();
4194+
virtual void h() noexcept = delete;
4195+
};
4196+
4197+
struct D: B {
4198+
void f(); // error
4199+
void g() noexcept; // OK
4200+
void h() = delete; // OK
4201+
};
4202+
\end{codeblock}
4203+
4204+
The declaration of
4205+
\tcode{D::f}
4206+
is ill-formed because it
4207+
has a potentially-throwing exception specification,
4208+
whereas
4209+
\tcode{B::f}
4210+
has a non-throwing exception specification.
4211+
\end{example}
4212+
4213+
\pnum
4214+
An expression $E$ is
4215+
\defnx{potentially-throwing}{potentially-throwing!expression} if
4216+
\begin{itemize}
4217+
\item
4218+
$E$ is a function call\iref{expr.call}
4219+
whose \grammarterm{postfix-expression}
4220+
has a function type,
4221+
or a pointer-to-function type,
4222+
with a potentially-throwing exception specification,
4223+
or
4224+
\item
4225+
$E$ implicitly invokes a function
4226+
(such as an overloaded operator,
4227+
an allocation function in a \grammarterm{new-expression},
4228+
a constructor for a function argument,
4229+
or a destructor if $E$ is a full-expression\iref{intro.execution})
4230+
that has a potentially-throwing exception specification,
4231+
or
4232+
\item
4233+
$E$ is a \grammarterm{throw-expression}\iref{expr.throw},
4234+
or
4235+
\item
4236+
$E$ is a \keyword{dynamic_cast} expression that casts to a reference type and
4237+
requires a runtime check\iref{expr.dynamic.cast},
4238+
or
4239+
\item
4240+
$E$ is a \keyword{typeid} expression applied to a
4241+
(possibly parenthesized) built-in unary \tcode{*} operator
4242+
applied to a pointer to a
4243+
polymorphic class type\iref{expr.typeid},
4244+
or
4245+
\item
4246+
any of the immediate subexpressions\iref{intro.execution}
4247+
of $E$ is potentially-throwing.
4248+
\end{itemize}
4249+
4250+
\pnum
4251+
An implicitly-declared constructor for a class \tcode{X},
4252+
or a constructor without a \grammarterm{noexcept-specifier}
4253+
that is defaulted on its first declaration,
4254+
has a potentially-throwing exception specification
4255+
if and only if
4256+
any of the following constructs is potentially-throwing:
4257+
\begin{itemize}
4258+
\item
4259+
the invocation of a constructor selected by overload resolution
4260+
in the implicit definition of the constructor
4261+
for class \tcode{X}
4262+
to initialize a potentially constructed subobject, or
4263+
\item
4264+
a subexpression of such an initialization,
4265+
such as a default argument expression, or,
4266+
\item
4267+
for a default constructor, a default member initializer.
4268+
\end{itemize}
4269+
\begin{note}
4270+
Even though destructors for fully-constructed subobjects
4271+
are invoked when an exception is thrown
4272+
during the execution of a constructor\iref{except.ctor},
4273+
their exception specifications do not contribute
4274+
to the exception specification of the constructor,
4275+
because an exception thrown from such a destructor
4276+
would call the function \tcode{std::terminate}
4277+
rather than escape the constructor\iref{except.throw,except.terminate}.
4278+
\end{note}
4279+
4280+
\pnum
4281+
The exception specification for an implicitly-declared destructor,
4282+
or a destructor without a \grammarterm{noexcept-specifier},
4283+
is potentially-throwing if and only if
4284+
any of the destructors
4285+
for any of its potentially constructed subobjects
4286+
has a potentially-throwing exception specification or
4287+
the destructor is virtual and the destructor of any virtual base class
4288+
has a potentially-throwing exception specification.
4289+
4290+
\pnum
4291+
The exception specification for an implicitly-declared assignment operator,
4292+
or an assignment-operator without a \grammarterm{noexcept-specifier}
4293+
that is defaulted on its first declaration,
4294+
is potentially-throwing if and only if
4295+
the invocation of any assignment operator
4296+
in the implicit definition is potentially-throwing.
4297+
4298+
\pnum
4299+
A deallocation function\iref{basic.stc.dynamic.deallocation}
4300+
with no explicit \grammarterm{noexcept-specifier}
4301+
has a non-throwing exception specification.
4302+
4303+
\pnum
4304+
The exception specification for a comparison operator function\iref{over.binary}
4305+
without a \grammarterm{noexcept-specifier}
4306+
that is defaulted on its first declaration
4307+
is potentially-throwing if and only if
4308+
any expression
4309+
in the implicit definition is potentially-throwing.
4310+
4311+
\pnum
4312+
\begin{example}
4313+
\begin{codeblock}
4314+
struct A {
4315+
A(int = (A(5), 0)) noexcept;
4316+
A(const A&) noexcept;
4317+
A(A&&) noexcept;
4318+
~A();
4319+
};
4320+
struct B {
4321+
B() noexcept;
4322+
B(const B&) = default; // implicit exception specification is \tcode{\keyword{noexcept}(\keyword{true})}
4323+
B(B&&, int = (throw 42, 0)) noexcept;
4324+
~B() noexcept(false);
4325+
};
4326+
int n = 7;
4327+
struct D : public A, public B {
4328+
int * p = new int[n];
4329+
// \tcode{D::D()} potentially-throwing, as the \keyword{new} operator may throw \tcode{bad_alloc} or \tcode{bad_array_new_length}
4330+
// \tcode{D::D(const D\&)} non-throwing
4331+
// \tcode{D::D(D\&\&)} potentially-throwing, as the default argument for \tcode{B}'s constructor may throw
4332+
// \tcode{D::\~D()} potentially-throwing
4333+
};
4334+
\end{codeblock}
4335+
Furthermore, if
4336+
\tcode{A::\~{}A()}
4337+
were virtual,
4338+
the program would be ill-formed since a function that overrides a virtual
4339+
function from a base class
4340+
shall not have a potentially-throwing exception specification
4341+
if the base class function has a non-throwing exception specification.
4342+
\end{example}
4343+
4344+
\pnum
4345+
An exception specification is considered to be \defnx{needed}{needed!exception specification} when:
4346+
\begin{itemize}
4347+
\item in an expression, the function is selected by
4348+
overload resolution\iref{over.match,over.over};
4349+
4350+
\item the function is odr-used\iref{term.odr.use} or, if it appears in an
4351+
unevaluated operand, would be odr-used if the expression were
4352+
potentially-evaluated;
4353+
4354+
\item the exception specification is compared to that of another
4355+
declaration (e.g., an explicit specialization or an overriding virtual
4356+
function);
4357+
4358+
\item the function is defined; or
4359+
4360+
\item the exception specification is needed for a defaulted
4361+
function that calls the function.
4362+
\begin{note}
4363+
A defaulted declaration does not require the
4364+
exception specification of a base member function to be evaluated
4365+
until the implicit exception specification of the derived
4366+
function is needed, but an explicit \grammarterm{noexcept-specifier} needs
4367+
the implicit exception specification to compare against.
4368+
\end{note}
4369+
\end{itemize}
4370+
The exception specification of a defaulted
4371+
function is evaluated as described above only when needed; similarly, the
4372+
\grammarterm{noexcept-specifier} of a specialization of a function
4373+
template or member function of a class template is instantiated only when
4374+
needed.
4375+
%
4376+
\indextext{exception specification|)}
4377+
41124378
\rSec3[dcl.fct.default]{Default arguments}%
41134379
\indextext{declaration!default argument|(}
41144380

0 commit comments

Comments
 (0)