GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing eel.is — [basic.contract.eval] 6 Basics [basic]6.11 Contract assertions [basic.contract]6.11.2 Evaluation [basic.contract.eval]An evaluation of a contract assertion
uses one of the following four evaluation semantics:
ignore,
observe,
enforce, or
quick-enforce. Observe, enforce, and quick-enforce are checking semantics;
enforce and quick-enforce are terminating semantics. It is
implementation-defined
which evaluation semantic is used
for any given evaluation of a contract assertion. [Note 1: The range and flexibility of available choices of
evaluation semantics depends on the implementation
and need not allow all four evaluation semantics as possibilities. The evaluation semantics can differ
for different evaluations of the same contract assertion,
including evaluations during constant evaluation. — end note]Recommended practice: An implementation should provide
the option to translate a program
such that all evaluations of contract assertions use the ignore semantic
as well as
the option to translate a program
such that all evaluations of contract assertions use the enforce semantic. By default,
evaluations of contract assertions should use the enforce semantic. The evaluation of a contract assertion using the ignore semantic has no effect. [Note 2: The predicate is potentially evaluated ([basic.def.odr]),
but not evaluated. — end note]The evaluation A of a contract assertion
using a checking semantic
determines the value of the predicate. It is unspecified
whether the predicate is evaluated. Let B be the value that would result from evaluating the predicate. [Note 3: To determine whether a predicate would evaluate
to true or false,
an alternative evaluation
that produces the same value as the predicate
but has no side effects
can occur. [Example 1: struct S {
mutable int g = 5;
} s;
void f()
pre(( s.g++, false )); // #1
void g()
{
f(); // Increment of s.g might not occur, even if #1 uses a checking semantic.
}
— end example] There is an observable checkpoint ([intro.abstract]) C
that happens before A
such that any other evaluation
that happens before A
also happens before C. A contract violation occurs when
[Note 4: If B is true,
no contract violation occurs and
control flow continues normally
after the point of evaluation of the contract assertion. The evaluation of the predicate
can fail to produce a value
without causing a contract violation,
for example,
by calling longjmp ([csetjmp.syn])
or terminating the program. — end note]If a contract violation occurs
in a context that is manifestly constant-evaluated ([expr.const.defns]),
and the evaluation semantic is
a terminating semantic,
the program is ill-formed. [Note 5: A diagnostic is produced
if the evaluation semantic is observe ([intro.compliance]). — end note][Note 6: Different evaluation semantics
chosen for the same contract assertion
in different translation units
can result in
violations of the one-definition rule ([basic.def.odr])
when a contract assertion has side effects
that alter the value produced by a constant expression. [Example 2: constexpr int f(int i)
{
contract_assert((++const_cast<int&>(i), true));
return i;
}
inline void g()
{
int a[f(1)]; // size dependent on the evaluation semantic of contract_assert above
}
— end example] When the program is contract-terminated,
it is
implementation-defined
(depending on context) whether
[Note 8: Performing the actions of
std::terminate or std::abort
without actually making a library call
is a conforming implementation of
contract-termination ([intro.abstract]). — end note]If a contract violation occurs
in a context that is not manifestly constant-evaluated
and the evaluation semantic is quick-enforce,
the program is contract-terminated. If a contract violation occurs
in a context that is not manifestly constant-evaluated
and the evaluation semantic is enforce or observe,
the contract-violation handler ([basic.contract.handler])
is invoked with an lvalue referring to
an object v
of type const std::contracts::contract_violation ([support.contract.violation])
containing information about the contract violation. Storage for v
is allocated in an unspecified manner
except as noted in [basic.stc.dynamic.allocation]. The lifetime of v
persists for the duration
of the invocation of the contract-violation handler. If the contract violation occurred
because the evaluation of the predicate
exited via an exception,
the contract-violation handler is invoked
from within an active implicit handler
for that exception ([except.handle]). If the contract-violation handler
returns normally
and the evaluation semantic is observe,
that implicit handler
is no longer considered active. If the contract-violation handler
returns normally
and the evaluation semantic is enforce,
the program is contract-terminated;
if violation occurred
as the result of an uncaught exception
from the evaluation of the predicate,
the implicit handler
remains active when contract termination occurs. There is an observable checkpoint ([intro.abstract]) C
that happens after the contract-violation handler returns normally
such that any other evaluation
that happens after the contract-violation handler returns
also happens after C. [Note 11: The terminating semantics terminate the program
if execution would otherwise continue normally
past a contract violation:
the enforce semantic provides the opportunity to
log information about the contract violation
before terminating the program
or to throw an exception to avoid termination,
and the quick-enforce semantic is intended
to terminate the program as soon as possible
as well as
to minimize the impact of contract checks
on the generated code size. Conversely,
the observe semantic
provides the opportunity to
log information about the contract violation
without having to terminate the program. — end note]If a contract-violation handler
invoked from the evaluation of a function contract assertion ([dcl.contract.func])
exits via an exception,
the behavior is as if
the function body exits via that same exception. [Note 12: A function-try-block ([except.pre])
is the function body when present
and thus does not
have an opportunity to catch the exception. If the function
has a non-throwing exception specification,
the function std::terminate is invoked ([except.terminate]). — end note][Note 13: If a contract-violation handler
invoked from an assertion-statement ([stmt.contract.assert])
exits via an exception,
the search for a handler
continues from the execution of that statement. — end note]To evaluate in sequence a list R of contract assertions:
[Example 3: void f(int i)
{
contract_assert(i > 0); // #1
contract_assert(i < 10); // #2
// valid sequence of evaluations: #1 #2
// valid sequence of evaluations: #1 #1 #2 #2
// valid sequence of evaluations: #1 #2 #1 #2
// valid sequence of evaluations: #1 #2 #2 #1
// invalid sequence of evaluations: #2 #1
}
— end example] |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |