<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<title>Allowing contract predicates on non-first declarations</title>

	<style>
	p {text-align:justify}
	li {text-align:justify}
	blockquote.note
	{
		background-color:#E0E0E0;
		padding-left: 15px;
		padding-right: 15px;
		padding-top: 1px;
		padding-bottom: 1px;
	}
	ins {color:#00A000}
	del {color:#A00000}
	</style>
</head>
<body>

<address align=right>
Document number: P1320R1
<br/>
Audience: EWG
<br/>
<br/>
<a href="mailto:ville.voutilainen@gmail.com">Ville Voutilainen</a><br/>
2019-01-20<br/>
</address>
<hr/>
<h1 align=center>Allowing contract predicates on non-first declarations</h1>

<h2>Abstract</h2>
<p>
  This paper proposes allowing contract predicates on non-first
  declarations for a member function. The rationale of doing so is,
  in a nutshell, to allow preconditions and postconditions
  to be implementation details. This thus also introduces the
  ability to redeclare a member function with a non-defining
  redeclaration.
</p>

<h2>Rationale</h2>

<p>
  There are users that do not want to expose a contract checking
  mechanism in their class interfaces; there may be an English
  contract, but the language-level contract enforcement mechanism
  is an implementation detail that function declarations in
  a class definition should not expose.
</p>
<p>
  It is probable that some would suggest that such use cases
  could be handled with contract assertions in function bodies.
  The reason why this paper proposes allowing contract predicates
  on non-first declarations is that
  <ul>
    <li>In some cases, there is no body to put an assertion in;
      defaulted functions and pure virtual functions are examples
      of this.</li>
    <li>For postconditions, postconditions are guaranteed to
      be checked (when checking is enabled in the first place) at function
      exit; relying on contract assertions is more error-prone.
  </ul>
</p>

<h2>Usage examples</h2>

<p>
  We basically propose being able to do this:<pre>
    <code>
      struct X
      {
          void f();
      };

      void X::f() [[expects: foo]]
      {
         ...
      }
    </code>
  </pre>
</p>
<p>
  In addition, though, what is also proposed is this:<pre>
    <code>
      struct X
      {
          void f();
      };
      void X::f() [[expects: foo]];

      // definition in a separate translation unit
      void X::f() [[expects: foo]]
      {
         ...
      }
    </code>
  </pre>
</p>

<h2>Implementation impact, semantic restrictions</h2>

<p>
  Allowing contract predicates on a non-first declaration
  probably means that in some such cases, the checking code
  can't be laid down at the call site unless the definition
  is also seen by the compiler.
</p>

<p>
  This leads to an implementation concern about being able
  to decide whether all contract-checking is always done
  at the definition site, or whether it's possible to
  allow the caller to do that.
</p>

<p>
  Based on an explanation by an implementation vendor,
  what we need to do is as follows:
  <ol>
    <li>If a class definition has a member function declaration
      <em>without</em> a contract on it, contract checking
      can be done at the call site if and only if the caller
      sees another declaration with a contract on it and the
      definition also sees such a declaration (possibly being
      one itself).
    <li>If a class definition has a member function declaration
      <em>with</em> a contract on it, the contract checking
      can be done at the call site regardless of other declarations.</li>
    <li>If the member function declaration in the class definition
      did not have a contract, and an outside-of-class declaration
      visible to the caller has a contract, and there is no
      declaration visible at the
      site of the definition with a contract on it, the program
      is ill-formed, no diagnostic required.
  </ol>
</p>

<h2>Wording</h2>

<p>
  In [class.mfct]/2, remove the redeclaration restriction:
  <pre><blockquote><del>Except for member function definitions
that appear outside of a class definition, and except for
explicit specializations of member functions of class
templates and member function templates (12.8) appearing
outside of the class definition, a member function
shall not be redeclared.</del>
</blockquote></pre>      
<p>
	
<p>In [dcl.attr.contract.cond]/1, modify as follows:
  <pre><blockquote>A contract condition is a precondition or a postcondition.
<ins>For a non-member function, </ins><del>T</del><ins>t</ins>he first declaration of a function shall specify
all contract conditions (if any) of the function. <ins>
For a member function, a member function redeclaration outside a class
definition may specify contract conditions different from the ones
in the declaration inside a class definition if the declaration
inside a class definition had no contract conditions.</ins>
Subsequent declarations shall either specify no contract
conditions or the same list of contract conditions;
no diagnostic is required if corresponding conditions
will always evaluate to the same value.
<ins>For a non-member function, </ins><del>T</del><ins>t</ins>he
list of contract conditions of a function shall be the same if
the declarations of that function appear in different translation units;
no diagnostic required. <ins>For a member function, the
list of contract conditions of a function shall be the same if
the redeclarations outside a class definition of that function appear
in different translation units; no diagnostic required.
[Note: a declaration in a class definition and a declaration
outside the class definition may have different lists of contract conditions. --end note]</ins>
</blockquote></pre>
</p>
</body>

</html>
