Skip to content

Commit 886de55

Browse files
committed
[except.spec] Exception specifications are function declarators
1 parent c7dc821 commit 886de55

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
@@ -4422,6 +4422,272 @@
44224422
\indextext{declaration!default argument|)}%
44234423
\indextext{declarator!meaning of|)}
44244424

4425+
\rSec3[except.spec]{Exception specifications}%
4426+
\indextext{exception specification|(}
4427+
4428+
\pnum
4429+
The predicate indicating whether a function cannot exit via an exception
4430+
is called the \defn{exception specification} of the function.
4431+
If the predicate is false,
4432+
the function has a
4433+
\indextext{exception specification!potentially-throwing}%
4434+
\defnx{potentially-throwing exception specification}%
4435+
{potentially-throwing!exception specification},
4436+
otherwise it has a
4437+
\indextext{exception specification!non-throwing}%
4438+
\defn{non-throwing exception specification}.
4439+
The exception specification is either defined implicitly,
4440+
or defined explicitly
4441+
by using a \grammarterm{noexcept-specifier}
4442+
as a suffix of a function declarator\iref{dcl.fct}.
4443+
4444+
\begin{bnf}
4445+
\nontermdef{noexcept-specifier}\br
4446+
\keyword{noexcept} \terminal{(} constant-expression \terminal{)}\br
4447+
\keyword{noexcept}\br
4448+
\end{bnf}
4449+
4450+
\pnum
4451+
\indextext{exception specification!noexcept!constant expression and}%
4452+
In a \grammarterm{noexcept-specifier}, the \grammarterm{constant-expression},
4453+
if supplied, shall be a contextually converted constant expression
4454+
of type \keyword{bool}\iref{expr.const};
4455+
that constant expression is the exception specification of
4456+
the function type in which the \grammarterm{noexcept-specifier} appears.
4457+
A \tcode{(} token that follows \keyword{noexcept} is part of the
4458+
\grammarterm{noexcept-specifier} and does not commence an
4459+
initializer\iref{dcl.init}.
4460+
The \grammarterm{noexcept-specifier} \keyword{noexcept}
4461+
without a \grammarterm{constant-expression}
4462+
is
4463+
equivalent to the \grammarterm{noexcept-specifier}
4464+
\tcode{\keyword{noexcept}(\keyword{true})}.
4465+
\begin{example}
4466+
\begin{codeblock}
4467+
void f() noexcept(sizeof(char[2])); // error: narrowing conversion of value 2 to type \keyword{bool}
4468+
void g() noexcept(sizeof(char)); // OK, conversion of value 1 to type \keyword{bool} is non-narrowing
4469+
\end{codeblock}
4470+
\end{example}
4471+
4472+
\pnum
4473+
If a declaration of a function
4474+
does not have a \grammarterm{noexcept-specifier},
4475+
the declaration has a potentially throwing exception specification
4476+
unless it is a destructor or a deallocation function
4477+
or is defaulted on its first declaration,
4478+
in which cases the exception specification
4479+
is as specified below
4480+
and no other declaration for that function
4481+
shall have a \grammarterm{noexcept-specifier}.
4482+
In an explicit instantiation\iref{temp.explicit}
4483+
a \grammarterm{noexcept-specifier} may be specified,
4484+
but is not required.
4485+
If a \grammarterm{noexcept-specifier} is specified
4486+
in an explicit instantiation,
4487+
the exception specification shall be the same as
4488+
the exception specification of all other declarations of that function.
4489+
A diagnostic is required only if the
4490+
exception specifications are not the same
4491+
within a single translation unit.
4492+
4493+
\pnum
4494+
\indextext{exception specification!virtual function and}%
4495+
If a virtual function has a
4496+
non-throwing exception specification,
4497+
all declarations, including the definition, of any function
4498+
that overrides that virtual function in any derived class
4499+
shall have a non-throwing
4500+
exception specification,
4501+
unless the overriding function is defined as deleted.
4502+
\begin{example}
4503+
\begin{codeblock}
4504+
struct B {
4505+
virtual void f() noexcept;
4506+
virtual void g();
4507+
virtual void h() noexcept = delete;
4508+
};
4509+
4510+
struct D: B {
4511+
void f(); // error
4512+
void g() noexcept; // OK
4513+
void h() = delete; // OK
4514+
};
4515+
\end{codeblock}
4516+
4517+
The declaration of
4518+
\tcode{D::f}
4519+
is ill-formed because it
4520+
has a potentially-throwing exception specification,
4521+
whereas
4522+
\tcode{B::f}
4523+
has a non-throwing exception specification.
4524+
\end{example}
4525+
4526+
\pnum
4527+
An expression $E$ is
4528+
\defnx{potentially-throwing}{potentially-throwing!expression} if
4529+
\begin{itemize}
4530+
\item
4531+
$E$ is a function call\iref{expr.call}
4532+
whose \grammarterm{postfix-expression}
4533+
has a function type,
4534+
or a pointer-to-function type,
4535+
with a potentially-throwing exception specification,
4536+
or
4537+
\item
4538+
$E$ implicitly invokes a function
4539+
(such as an overloaded operator,
4540+
an allocation function in a \grammarterm{new-expression},
4541+
a constructor for a function argument,
4542+
or a destructor if $E$ is a full-expression\iref{intro.execution})
4543+
that has a potentially-throwing exception specification,
4544+
or
4545+
\item
4546+
$E$ is a \grammarterm{throw-expression}\iref{expr.throw},
4547+
or
4548+
\item
4549+
$E$ is a \keyword{dynamic_cast} expression that casts to a reference type and
4550+
requires a runtime check\iref{expr.dynamic.cast},
4551+
or
4552+
\item
4553+
$E$ is a \keyword{typeid} expression applied to a
4554+
(possibly parenthesized) built-in unary \tcode{*} operator
4555+
applied to a pointer to a
4556+
polymorphic class type\iref{expr.typeid},
4557+
or
4558+
\item
4559+
any of the immediate subexpressions\iref{intro.execution}
4560+
of $E$ is potentially-throwing.
4561+
\end{itemize}
4562+
4563+
\pnum
4564+
An implicitly-declared constructor for a class \tcode{X},
4565+
or a constructor without a \grammarterm{noexcept-specifier}
4566+
that is defaulted on its first declaration,
4567+
has a potentially-throwing exception specification
4568+
if and only if
4569+
any of the following constructs is potentially-throwing:
4570+
\begin{itemize}
4571+
\item
4572+
the invocation of a constructor selected by overload resolution
4573+
in the implicit definition of the constructor
4574+
for class \tcode{X}
4575+
to initialize a potentially constructed subobject, or
4576+
\item
4577+
a subexpression of such an initialization,
4578+
such as a default argument expression, or,
4579+
\item
4580+
for a default constructor, a default member initializer.
4581+
\end{itemize}
4582+
\begin{note}
4583+
Even though destructors for fully-constructed subobjects
4584+
are invoked when an exception is thrown
4585+
during the execution of a constructor\iref{except.ctor},
4586+
their exception specifications do not contribute
4587+
to the exception specification of the constructor,
4588+
because an exception thrown from such a destructor
4589+
would call the function \tcode{std::terminate}
4590+
rather than escape the constructor\iref{except.throw,except.terminate}.
4591+
\end{note}
4592+
4593+
\pnum
4594+
The exception specification for an implicitly-declared destructor,
4595+
or a destructor without a \grammarterm{noexcept-specifier},
4596+
is potentially-throwing if and only if
4597+
any of the destructors
4598+
for any of its potentially constructed subobjects
4599+
has a potentially-throwing exception specification or
4600+
the destructor is virtual and the destructor of any virtual base class
4601+
has a potentially-throwing exception specification.
4602+
4603+
\pnum
4604+
The exception specification for an implicitly-declared assignment operator,
4605+
or an assignment-operator without a \grammarterm{noexcept-specifier}
4606+
that is defaulted on its first declaration,
4607+
is potentially-throwing if and only if
4608+
the invocation of any assignment operator
4609+
in the implicit definition is potentially-throwing.
4610+
4611+
\pnum
4612+
A deallocation function\iref{basic.stc.dynamic.deallocation}
4613+
with no explicit \grammarterm{noexcept-specifier}
4614+
has a non-throwing exception specification.
4615+
4616+
\pnum
4617+
The exception specification for a comparison operator function\iref{over.binary}
4618+
without a \grammarterm{noexcept-specifier}
4619+
that is defaulted on its first declaration
4620+
is potentially-throwing if and only if
4621+
any expression
4622+
in the implicit definition is potentially-throwing.
4623+
4624+
\pnum
4625+
\begin{example}
4626+
\begin{codeblock}
4627+
struct A {
4628+
A(int = (A(5), 0)) noexcept;
4629+
A(const A&) noexcept;
4630+
A(A&&) noexcept;
4631+
~A();
4632+
};
4633+
struct B {
4634+
B() noexcept;
4635+
B(const B&) = default; // implicit exception specification is \tcode{\keyword{noexcept}(\keyword{true})}
4636+
B(B&&, int = (throw 42, 0)) noexcept;
4637+
~B() noexcept(false);
4638+
};
4639+
int n = 7;
4640+
struct D : public A, public B {
4641+
int * p = new int[n];
4642+
// \tcode{D::D()} potentially-throwing, as the \keyword{new} operator may throw \tcode{bad_alloc} or \tcode{bad_array_new_length}
4643+
// \tcode{D::D(const D\&)} non-throwing
4644+
// \tcode{D::D(D\&\&)} potentially-throwing, as the default argument for \tcode{B}'s constructor may throw
4645+
// \tcode{D::\~D()} potentially-throwing
4646+
};
4647+
\end{codeblock}
4648+
Furthermore, if
4649+
\tcode{A::\~{}A()}
4650+
were virtual,
4651+
the program would be ill-formed since a function that overrides a virtual
4652+
function from a base class
4653+
shall not have a potentially-throwing exception specification
4654+
if the base class function has a non-throwing exception specification.
4655+
\end{example}
4656+
4657+
\pnum
4658+
An exception specification is considered to be \defnx{needed}{needed!exception specification} when:
4659+
\begin{itemize}
4660+
\item in an expression, the function is selected by
4661+
overload resolution\iref{over.match,over.over};
4662+
4663+
\item the function is odr-used\iref{term.odr.use} or, if it appears in an
4664+
unevaluated operand, would be odr-used if the expression were
4665+
potentially-evaluated;
4666+
4667+
\item the exception specification is compared to that of another
4668+
declaration (e.g., an explicit specialization or an overriding virtual
4669+
function);
4670+
4671+
\item the function is defined; or
4672+
4673+
\item the exception specification is needed for a defaulted
4674+
function that calls the function.
4675+
\begin{note}
4676+
A defaulted declaration does not require the
4677+
exception specification of a base member function to be evaluated
4678+
until the implicit exception specification of the derived
4679+
function is needed, but an explicit \grammarterm{noexcept-specifier} needs
4680+
the implicit exception specification to compare against.
4681+
\end{note}
4682+
\end{itemize}
4683+
The exception specification of a defaulted
4684+
function is evaluated as described above only when needed; similarly, the
4685+
\grammarterm{noexcept-specifier} of a specialization of a function
4686+
template or member function of a class template is instantiated only when
4687+
needed.
4688+
%
4689+
\indextext{exception specification|)}
4690+
44254691
\rSec1[dcl.init]{Initializers}%
44264692

44274693
\rSec2[dcl.init.general]{General}%

0 commit comments

Comments
 (0)