<!DOCTYPE html>
<html lang="en"><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">


<meta name="viewport" content="width=device-width, initial-scale=1">


<style>
pre {font-family: "Consolas", "Lucida Console", monospace; margin-left:20pt; }
code {font-family: "Consolas", "Lucida Console", monospace; }
pre > i   { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
code > i  { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
pre > em  { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
code > em { font-family: "Consolas", "Lucida Console", monospace;  font-style:italic; }
/*body { color: #000000; background-color: #FFFFFF; }*/

@media (prefers-color-scheme: dark) {
	body { background: #111; color:  #ccc; }
	a { color:  #38f; }
	a:visited { color:  #a4d; }
	.sect { color:  #ccc; }
}

@media (prefers-color-scheme: light) {
	body { background:  white; color: black; }
}   

del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }

p.example   { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract  { margin-left: 2em; background-color: #F5F6A2;  border: 1px solid #E1E28E; }

p.function    { }
.attribute    { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

.editor { color: #4444BB; font-style: normal; background-color: #DDDDDD; }

tab { padding-left: 4em; }
tab3 { padding-left: 3em; }

.link { float: right }

blockquote.std    { color: #000000; background-color: #F1F1F1;  border: 1px solid #D1D1D1;  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;  color: #000000; background-color: #FFEBFF;  border: 1px solid #ECD7EC;  padding-left: 0.5em; padding-right: 0.5em; ; }
blockquote.stdins { text-decoration: underline;  color: #000000; background-color: #C8FFC8;  border: 1px solid #B3EBB3; padding: 0.5em; }
table.header { border: 0px; border-spacing: 0;  margin-left: 0px; font-style: normal; }
table.poll { border: 1px solid black; border-spacing: 0px;  margin-left: 0px; font-style: normal; }
table { border: 1px solid black; border-spacing: 0px;  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;  padding-left: 0.4em; border: none;  padding-right: 0.4em; border: none; }
td { text-align: left;  padding-left: 0.4em; border: none;  padding-right: 0.4em; border: none; }

.revision   { /*color: #005599;*/ }
.grammar { list-style-type:none }

</style>

<title>Noexcept vs contract violations</title>

</head>
<body>


<table class="header"><tbody>
  <tr>
    <th>Document number:&nbsp;&nbsp;</th><th> </th><td>P2858R0</td>
  </tr>
  <tr>
    <th>Date:&nbsp;&nbsp;</th><th> </th><td>2023-05-12</td>
  </tr>
  <tr>
    <th>Audience:&nbsp;&nbsp;</th><th> </th><td>SG21</td>
  </tr>
  <tr>
    <th>Reply-to:&nbsp;&nbsp;</th><th> </th><td>
        <address>Andrzej Krzemieński &lt;akrzemi1 at gmail dot com&gt;</address>	
      </td>
  </tr>
</tbody></table>


<h1>Noexcept vs contract violations</h1>



<p>
    The purpose of this document is to highlight some design issues
    concerning <code>noexcept</code> functions with preconditions or postconditions
    or any contract checks evaluated inside their bodies.
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html"
       title="Minimum Contract Support: either No_eval or Eval_and_abort&rdquo;">[P2388R4]</a>
    proposed only hard <code>std::abort()</code> upon detecting a contract violation,
    therefore it didn't have to address these questions. Now that we are considering
    extensions like <em>Eval_or_throw</em> (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2698r0.pdf"
   title="Bjarne Stroustrup, &ldquo;Unconditional termination is a serious problem&rdquo;">[P2698R0]</a>)
    or contract violation handlers (<a href="https://isocpp.org/files/papers/P2811R2.pdf"
   title="Joshua Berne, &ldquo;Contract-Violation Handlers&rdquo;">[P2811R2]</a>),
    the interaction with <code>noexcept</code> has to be designed.
</p>

<h2>The meaning of <code>noexcept</code></h2>

<p> The original motivation for adding <code>noexcept</code> was
    for users to annotate their move constructors with it, in order that 
    the <code>vector</code> implementation could statically detect that property
    and select the most appropriate algorithm for providing the strong exception safety
    guarantee. The problem is described in
    <a href="https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2855.html"
    title="Douglas Gregor, David Abrahams, &ldquo;Rvalue References and Exception Safety&rdquo;">[N2855]</a>.
    In this view, the motivation for putting the <code>noexcept</code> specifier is to inform
    generic components which implementation to apply. It has only loose connection with whether
    a function throws or not. That is, the specification for function <code>f</code> 
    can say that it never throws an exception but <code>f</code> doesn't have to be <code>noexcept</code>,
    and conversely: a function can be declared <code>noexcept</code> and it can still throw an 
    exception in the function body. Such exception will not leave the function body 
    (due to a call to <code>std::terminate</code>) but it is still an undesired situation, detectable only dynamically.
    The way <code>noexcept</code> specifier is consumed is via operator <code>noexcept</code>,
    type traits such as <code>std::is_nothrow_move_constructible</code>, or more directly via
    type system:
    </p>

<pre>
void fun() noexcept;

void overload(void(*)());          <em>// #1</em>
void overload(void(*)() noexcept); <em>// #2</em>

overload(&amp;fun);                    <em>// #2 selected</em>
</pre>

<p> Another view that people often present is that <code>noexcept</code> is a function's postcondition,
    much like the guarantee that a value produced by function <code>sqrt</code> is non-negative.
    However, this view overlooks one important aspect of a postcondition:
    a postcondition is a <em>conditional</em> guarantee: a function guarantees to satisfy the 
    postcondition only if its preconditions have been satisfied. If the function's precondition 
    is not satisfied, it is not required to satisfy its postcondition. To illustrate this,
    consider the following correct implementation of function <code>select_ptr</code>:</p>

<pre>
int* select_ptr(int* lhs, int* rhs, bool cond)
  [[pre: lhs != nullptr]]
  [[pre: rhs != nullptr]]
  [[post ans: ans != nullptr]]
{
  return cond ? rhs : lhs;
}
</pre>

<p> Clearly, this function can return a null pointer, if it is passed null pointers as
    arguments, but this is ok as the function is not bound by the contract if its
    precondition is violated. <code>noexcept</code>, on the other hand, is a property that has effect even if
   the function is called out of contract.</p>

<p> An author of a function can guarantee in the function's documentation that the function never
    throws when its precondition is satisfied, but they do not have to declare the function as
    <code>noexcept</code>. That is, the lack of <code>noexcept</code> does not imply the lack of
    no-throw guarantee.</p>


<h2>Can different translation modes alter the type system?</h2>

<p> Preconditions and postconditions are to be put on function declarations, 
    which means that if their expressions are runtime-evaluated, this evaluation
    happens somewhere between the caller and the callee. Now, if a contract violation
    handler &mdash; that can potentially throw &mdash; is added to the picture,
    the question arises, how this should affect language constructs that detect
    the <code>noexcept</code>.
    </p>

<pre>
void fun() noexcept [[pre: false]];

constexpr bool mystery = noexcept(fun());  <em>// what value??</em>

using nothrow_callback_t = void(*)() noexcept;
nothrow_callback_t p = fun;                <em>// compiles??</em>

void overload(void(*)());                  <em>// #1</em>
void overload(void(*)() noexcept);         <em>// #2</em>

overload(&amp;fun);                            <em>// which overload??</em>
</pre>

<p> Should the answer to these questions be different in different translation modes?
    Should different implementations be allowed to give different answers? This is what
    <a href="https://isocpp.org/files/papers/P2852R0.html"
       title="Tom Honermann, &ldquo;Contract violation handling semantics for the contracts MVP&rdquo;">[P2852R0]</a>
    proposes, with the possibility to strengthen this in the future.
</p>


<h2>No-fail, no-throw and similar guarantees</h2>


<p> Some contexts of a program require a no-fail guarantee while some other require a no-throw guarantee,
    and these two guarantees are different.</p>

<p> A no-fail guarantee is required as a building block for providing a strong &mdash; transactional &mdash; guarantee.
    This type of guarantee is often required from <code>swap</code> functions. They should be simple enough
    that there is no way that anything could fail when executing them. Similarly, on the other side of the interface,
    it is often possible to implement <code>swap</code> as a number of raw pointer assignments, so one
    can easily convince oneself that no fail is possible.</p>

<p> There are other situations where a fail is acceptable, but such failure should not be reported.
    In case a program reports failures via error codes or things like <code>std::expected</code>,
    the failure can simply be ignored; but in case of exceptions, where the information about failure
    is propagated by default, it is required that no exception is thrown even in the case of a failure.
    This is often the case for destructors: when they are used to release resources.
    Typically, a destructor is called in a function after the return object, if any, has been initialized,
    and the postcondition of the function has already been satisfied. In that case throwing
    an exception from the function would be a design error. Releasing a resource can fail,
    but this does not affect the satisfaction of the postconditions, so breaking the caller is
    not appropriate.</p>

<p> Obviously, a no-fail guarantee implies the no-throw guarantee, 
    but the implication doesn't work in the other direction.</p>

<p> Apart from these, we also have conditional no-fail guarantees: for ranges of input values.
    For instance, <code>vector&lt;T&gt;::at</code> guarantees no fail provided that the index does not exceed
    the size of the vector. Similarly,  <code>vector&lt;int&gt;::push_back</code> guarantees no fail,
    provided that the vector's capacity is greater than its size. The no-fail guarantee obviously is also
    predicated on satisfying the function's preconditions. As a consequence, the following is a valid 
    implementation of <code>vector&lt;T&gt;::operator[]</code>:
</p>

<pre>
const_reference vector&lt;T&gt;::operator[](size_type pos) const
  [[pre: pos &lt; this-&gt;size()]]
  <em>// no-fail</em> 
{
  return this-&gt;at(pos);
}
</pre>

<p> When programmers need to provide bodies of <em>no-fail</em> functions they can: </p>

<ul>
    <li>call other no-fail functions,</li>
    <li>call conditional no-fail functions, and make sure that their conditions are met.</li>
</ul>

<p> When programmers need to provide bodies of <em>no-throw</em> functions they can: </p>

<ul>
    <li>call other no-fail functions,</li>
    <li>call other no-throw functions, provided that a failure in the no-throw function does not affect the correctness
        of subsequent operations,</li>
    <li>call conditional no-fail functions, and make sure that their conditions are met,</li>
    <li>call any function but catch all exceptions thrown and conceal them.</li>
</ul>

<p> Naturally, all these guarantees cannot be expressed as attributes or specifiers on the function declaration.
    They can only be learned from the documentation of some sort. Only documentation can describe the 
    full contract of a given function. If we look at it from the perspective of a user, they can ask,
    where does a new C++ programmer should take the documentation from for the Standard Library?
    There is no easy answer to this question. Because of that there is a temptation to use
    <code>noexcept</code> specifier to identify no-throw guarantee, as a substitute for documentation.
    But this has its problems: the real no-fail guarantee is conditional: it depends on the input values.
    It is easy to accept for the case of <code>vector&lt;int&gt;::push_back</code>, less so
    for <code>vector&lt;T&gt;::operator[]</code>, but the situation is the same. The implementation
    of <code>vector&lt;T&gt;::operator[]</code> can only make guarantees in the case where the index
    is within a certain range of values. The function shouldn't be forced to make any guarantees
    for the cases where its precondition isn't satisfied. That is the point of a contract. No-fail,
    no-throw are also guarantees, so they should be (allowed to be) conditional. This is in
    contrast with the mechanics of <code>noexcept</code> which allows code transformations regardless
    if functions are called with their precondition satisfied or not.
    </p>

<p> One could say that if a function is called with its precondition violated then all bets are off
    and all the above reasoning can be discarded. But this is not entirely correct. 
    Calling a language feature out of contract is UB (Undefined Behavior), calling a Standard Library function out of contract
    is, at least for now, UB (even if of different kind), but calling user-defined functions out of 
    contract is not necessarily a UB. Consider the above example of <code>select_ptr</code>.
    Its implementation has no UB, not even on illegal inputs. Yet, because it specifies a precondition, it is not bound to offer any guarantee
    upon a violated precondition.</p>

<p> How about the situation where a function has no preconditions: it has defined semantics for every input value. Can we use
    <code>noexcept</code> on such function to mean no-throw guarantee? First, a precondition is more than just a program state
    that we can observe and give a true/false answer. A precondition may be "you can call <code>f</code> only if <code>g</code> 
    hasn't been called" or conversely "you can call <code>run</code> only if <code>init</code> has been called". These things can still
    can trigger a contract violation somewhere inside the implementation, but the function's input values (or the observable program
    state) are fine. 
    But there is also the question of behavior in the face of bugs. The caller may have done everything correctly,
    but the implementation of the function may have a bug that needs to be signaled via the contract violation handler.
    This is covered in the next section. </p>


<h2>Throwing from a <code>noexcept</code> function</h2>

<p> There is one clever use for a <code>noexcept</code> specifier. This is when I need my program to 
    terminate when a given function in a given context ends in failure that is reported with an exception.
    I can put a <code>noexcept</code> there to mean: convert an exception into a call to <code>std::terminate()</code>.
    We will assume that this use case is rare, and skip it from further analysis.</p>

<p> Other than the above, when a function author annotates it as <code>noexcept</code>,
    it means that they commit to providing implementation that <em>never</em> ends in
    exception. Causing the call to <code>std::terminate</code> is unintentional, and maybe
    unacceptable. Suppose we have a function with no precondition that is declared <code>noexcept</code>.
    Providing a no-fail implementation is known to be possible, but we have a bug in our implementation.
    If we have a contract support framework in place, bugs in the implementation can be detected 
    via contract declaration checks. Additionally, when a contract check can throw an exception upon
    any bug in the implementation declared in this way &mdash; such as in 
    <em>Eval_or_throw</em> mode (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2698r0.pdf"
   title="Bjarne Stroustrup, &ldquo;Unconditional termination is a serious problem&rdquo;">[P2698R0]</a>)
    or a throwing contract violation handler (<a href="https://isocpp.org/files/papers/P2811R2.pdf"
   title="Joshua Berne, &ldquo;Contract-Violation Handlers&rdquo;">[P2811R2]</a>) &mdash;
    we will end up throwing an exception from a <code>noexcept</code> function,
    and causing a call to <code>std::terminate()</code>. Is this an acceptable solution?
    One could say that if the program has a bug, you cannot expect anything of it.
    But on the other hand, one of the purposes of the contract support framework
    is to make programs behave reliably even in the face of an exception.</p>

<p> <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2698r0.pdf"
   title="Bjarne Stroustrup, &ldquo;Unconditional termination is a serious problem&rdquo;">[P2698R0]</a>
    argues that in some environments stopping a program is unacceptable. If we wanted to implement this
    requirement, we would have to do one of the following: </p>

<ul>
    <li>disallow throwing from the contract checks,</li>
    <li>disallow annotating functions as <code>noexcept</code>,</li>
    <li>drastically minimize/discourage the usage <code>noexcept</code> and tolerate the crashes in 
        these situations.</li>
</ul>

<p> If the third option is preferred, it would have to be accompanied by guidelines for:</p>

<ul>
    <li>WG21: how to specify the interfaces of the Standard Library functions,</li>
    <li>programmers: how to specify the interfaces of their functions.</li>
</ul>

<p> It should be noted that <code>noexcept</code> is declared implicitly for destructors and deallocation functions
    and these can also have preconditions, and they can surely have bugs detectable via the contract support framework mechanisms.
    Consider one example from <a href="https://isocpp.org/files/papers/P2784R0.html"
   title="Andrzej Krzemieński, &ldquo;Not halting the program after detected contract violation&rdquo;">[P2784R0]</a>:</p>

<pre>
class State 
{
  std::vector&lt;Column*&gt; _columns;
  unsigned _theColumn;

public:  
  bool invariant() const noexcept 
  {
    return _theColumn &lt; _columns.size() &amp;&amp; _columns[_theColumn] != nullptr;  
  }
  
  void alter() 
    [[pre: invariant()]]
    [[post: invariant()]];
  
  ~State() 
    [[pre: invariant()]] 
  {
     delete _columns[_theColumn];
  }
};
</pre>    

<p> If upon calling <code>state.alter()</code> its precondition is violated and this
    gets turned into an exception, during the stack unwinding we will need to call 
    the destructor of <code>state</code>. The destructor also has a precondition
    which would also be violated. This would trigger a second exception to be thrown.  
    </p> 

<p> Apart from implicit <code>noexcept</code>, there strong motivation for adding 
    the specifier explicitly is the original motivation from  
    <a href="https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2855.html"
        title="Douglas Gregor, David Abrahams, &ldquo;Rvalue References and Exception Safety&rdquo;">[N2855]</a>.
    Even move constructors can have bugs that will end up throwing exceptions 
    when a throwing contract violation handler is in place.
    </p>

<h2>Special-casing preconditions on library boundaries</h2>

<p> <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2780r0.html"
    title="Ville Voutilainen, &ldquo;Caller-side precondition checking, and Eval_and_throw&rdquo;">[P2780R0]</a>
    presents an important use case, where a program uses a third-party library. We do not want
    to check the contract violations in the used library, nor its postconditions: we trust the library.
    We only want to check contract violations in our program, which includes checking the preconditions
    of the library's functions where possible (it is unimplementable when these function are called via indirection).
    While this is the case worth supporting, the discussion about <code>noexcept</code> in this paper is
    an unnecessary distraction. Counter to what the paper suggests, its proposed solution does not address the problem
    of throwing violation handling mode: neither <em>Eval_or_throw</em> mode (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2698r0.pdf"
   title="Bjarne Stroustrup, &ldquo;Unconditional termination is a serious problem&rdquo;">[P2698R0]</a>)
    nor a throwing contract violation handler (<a href="https://isocpp.org/files/papers/P2811R2.pdf"
   title="Joshua Berne, &ldquo;Contract-Violation Handlers&rdquo;">[P2811R2]</a>).
    </p>

<p> Performing the precondition check <em>always</em> in the caller &mdash; which 
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2780r0.html"
   title="Ville Voutilainen, &ldquo;Caller-side precondition checking, and Eval_and_throw&rdquo;">[P2780R0]</a>
    essentially proposes &mdash; leaves the problems with the type system and type traits unanswered.
    It also does not prevent the calls to <code>std::terminate</code> when one <code>noexcept</code>
    function is called in another:</p>

<pre>
bool lib::compute(int i) noexcept [[pre: i &gt; 0]];

bool fun(int i) noexcept
{
  if (i &lt; 0) lib::compute(-i);
  else       lib::compute(i); <em>// bug on `i == 0`</em>
}
</pre>

<p> Here, if we call <code>fun(0)</code> we violate the precondition of <code>lib::compute</code>
    which triggers an exception in some mode. Even if an exception is thrown 
    outside of <code>lib::compute</code>, it is still called inside <code>fun</code>,
    which is also <code>noexcept</code>.
    </p>


<h2>Exceptions thrown from predicates</h2>

 <p> Another source of exceptions caused by the contract support framework,
     unrelated to the violation handler, it when the evaluation of the predicate
     throws one. <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html"
   title="Minimum Contract Support: either No_eval or Eval_and_abort&rdquo;">[P2388R4]</a>
     requires that this should end in calling <code>std::terminate()</code>.
     SG21 had a consensus in Kona 2023 meeting that it was undesired,
     however no single alternative had consensus.</p>

<p> This paper does not address this problem explicitly, however, a lot of discussion 
    related to throwing contract violation handlers also applies to throwing predicates.</p>



<h2>Some real life experience</h2>


<p> This section describes the author's experience with using throwing violation handlers.</p>

<p> In our production servers we use our own macro <code>IC_ASSERT</code>, which is evaluated in any "mode".
    In test builds contract violation ends in <code>std::abort()</code>, in order to collect a core dump
    and easily analyze the problem. In production builds we throw a special exception. This exception is 
    only called in the main server loop: the client transaction is aborted, the client is responded with an apology
    message, and the server proceeds to processing the next transaction, which is hopefully sufficiently different
    that it does not enter the same path (maybe a new plugin) as the previous one. Often &mdash; although 
    there is no guarantee &mdash; the stack unwinding is enough to recover from the bug.</p>

<p> This works satisfactorily due to a number of circumstances:</p>

<ol>
    <li>
        Macro <code>IC_ASSERT</code> is only used in the server code. We know it isn't used in the
        libraries we use. So, we control where it is put.
    </li>
    <li>
        We do not annotate functions as <code>noexcept</code>. Practically all the functions 
        provide only basic failure-safety guarantee. If anything goes wrong we just cancel
        either the entire client transaction, or skip a well isolated components.
    </li>
    <li>
        We can afford to crash the server. Other sibling servers then take over the traffic,
        so even if we accidentally throw from a destructor due to a violated contract,
        it is tolerable.
    </li>
</ol>



<h2>Conclusion</h2>

<p> In order to allow throwing from a contract runtime checks, we need to provide a clear
    semantics for all static checks that rely on the <code>noexcept</code> property:
    type traits, <code>noexcept</code>-operator, function types. For this we need
    a cleaner story for what <code>noexcept</code> specifier is. The model in this paper
    makes a distinction between a declaration of will for controlling overloads and a 
    no-fail guarantee dependent on the precondition satisfaction. Only the former requires a 
    syntactic marker to work, and conflating the two may not be beneficial. This takes us
    close to <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3248.pdf"
   title="Alisdair Meredith, John Lakos, &ldquo;noexcept Prevents Library Validation&rdquo;">[N3248]</a>,
    except that our motivation is not to enable library validation.
    </p>

<p> It is also possible to disallow throwing from a violation handler (for instance, 
    allow installing only <code>noexcept</code> contract violation handlers), if not at all,
    then only temporarily for the C++26 time frame. This would allow for violation handlers,
    but defer the specification of interactions with <code>noexcept</code> for the subsequent
    C++ release.
    </p>

<p> We also note that exceptions are not a good way to address the problem of applications that
    do want to stop in the face of the detected contract violation. They can be a cause
    for premature a termination on their own. In fact, a contract checking that can throw
    means that exceptions can now be thrown from any place, also functions without preconditions,
    which means that putting <code>noexcept</code> anywhere would be risky.</p>


<h2>Acknowledgments</h2>

<p>Joshua Berne has reviewed this document, and provided useful feedback.</p>


<h2><a class="sect" id="ref">References</a></h2>

<ul>

    <li>
        [N2855] — Douglas Gregor, David Abrahams,
        "Rvalue References and Exception Safety"<br>
        (<a href="https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2855.html">https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2855.html</a>).
    </li>
    <!--
    <a href="https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2855.html"
        title="Douglas Gregor, David Abrahams, &ldquo;Rvalue References and Exception Safety&rdquo;">[N2855]</a>
    -->

    <li>
        [N2983] — David Abrahams, Rani Sharoni, Doug Gregor,
        "Allowing Move Constructors to Throw"<br>
        (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2983.html"
            >https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2983.html</a>).
    </li>
    <!--
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2983.html"
        title="David Abrahams, Rani Sharoni, Doug Gregor, &ldquo;Allowing Move Constructors to Throw&rdquo;">[N2983]</a>
    -->

    <li>
        [N3248] — Alisdair Meredith, John Lakos,
        "noexcept Prevents Library Validation"<br>
        (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3248.pdf">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3248.pdf</a>).
    </li>
    <!--
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3248.pdf"
        title="Alisdair Meredith, John Lakos, &ldquo;noexcept Prevents Library Validation&rdquo;">[N3248]</a>
    -->


    <li>
        [P0542R5] — G. Dos Reis, J. D. Garcia, J. Lakos, A. Meredith, N. Myers, B. Stroustrup,
        "Support for contract based programming in C++" <br>
        (<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0542r5.html">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0542r5.html</a>).
    </li>
    <!--
    <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0542r5.html"
       title="G. Dos Reis, J. D. Garcia, J. Lakos, A. Meredith, N. Myers, B. Stroustrup, &ldquo;Support for contract based programming in C++&rdquo;">[P0542R5]</a>
    -->

    <li>
        [P2388R4] — Andrzej Krzemieński, Gašper Ažman,
        "Minimum Contract Support: either No_eval or Eval_and_abort" <br>
        (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html</a>).
    </li>
    <!--
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2388r4.html"
       title="Minimum Contract Support: either No_eval or Eval_and_abort&rdquo;">[P2388R4]</a>
    -->

    <li>
        [P2698R0] — Bjarne Stroustrup, "Unconditional termination is a serious problem" <br>
        (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2698r0.pdf">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2698r0.pdf</a>).
    </li>
    <!--
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2698r0.pdf"
       title="Bjarne Stroustrup, &ldquo;Unconditional termination is a serious problem&rdquo;">[P2698R0]</a>
    -->

    <li>
        [P2784R0] — Andrzej Krzemieński,
        "Not halting the program after detected contract violation" <br>
        (<a href="https://isocpp.org/files/papers/P2784R0.html">https://isocpp.org/files/papers/P2784R0.html</a>).
    </li>
    <!--
    <a href="https://isocpp.org/files/papers/P2784R0.html"
       title="Andrzej Krzemieński, &ldquo;Not halting the program after detected contract violation&rdquo;" >[P2784R0]</a>
    -->

    <li>
        [P2811R2] — Joshua Berne,
        "Contract-Violation Handlers"<br>
        (<a href="https://isocpp.org/files/papers/P2811R2.pdf">https://isocpp.org/files/papers/P2811R2.pdf</a>).
    </li>
    <!--
    <a href="https://isocpp.org/files/papers/P2811R2.pdf"
        title="Joshua Berne, &ldquo;Contract-Violation Handlers&rdquo;">[P2811R2]</a>
    -->

    <li>
        [P2780R0] — Ville Voutilainen,
        "Caller-side precondition checking, and Eval_and_throw"<br>
        (<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2780r0.html">
            https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2780r0.html
        </a>).
    </li>
    <!--
    <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2780r0.html"
        title="Ville Voutilainen, &ldquo;Caller-side precondition checking, and Eval_and_throw&rdquo;">[P2780R0]</a>
    -->

    <li>
        [P2852R0] — Tom Honermann,
        "Contract violation handling semantics for the contracts MVP"<br>
        (<a href="https://isocpp.org/files/papers/P2852R0.html">https://isocpp.org/files/papers/P2852R0.html</a>).
    </li>
    <!--
    <a href="https://isocpp.org/files/papers/P2852R0.html"
        title="Tom Honermann, &ldquo;Contract violation handling semantics for the contracts MVP&rdquo;">[P2852R0]</a>
    -->
    <!---->
    <!---->
    <!---->
    <!---->
    <!---->
    <!---->

</ul>



</body></html>