<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta name="generator" content="dascandy/fiets">
<title>
C++ contracts with regards to function pointers</title>
  <style type="text/css">
body {
  margin: 5em;
  font-family: sans-serif;
  hyphens: auto;
  line-height: 1.35;
}
ul {
  padding-left: 2em;
}
h1, h2, h3, h4 {
  position: relative;
  line-height: 1;
}
h1.title {
}
h2.subtitle {
}
h1.toc a, h2.toc a, h3.toc a, h4.toc a {
  text-decoration: none;
  color: #000000;
}
h1.toc a:hover, h2.toc a:hover, h3.toc a:hover, h4.toc a:hover {
  text-decoration: underline;
}
a.self-link {
  position: absolute;
  top: 0;
  left: calc(-1 * (3.5rem - 26px));
  width: calc(3.5rem - 26px);
  height: 2em;
  text-align: center;
  border: none;
  transition: opacity .2s;
  opacity: .5;
  font-family: sans-serif;
  font-weight: normal;
  font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
span.identifier {
  font-style: italic;
}
span.new {
  text-decoration: underline;
  background-color: #006e28;
}
div.code, span.code {
  font-family: Courier New, monospace;
  background-color: #e8e8e8;
  white-space: pre;
}
span.delete {
  text-decoration: line-through;
  background-color: #bf0303;
}
p.indent {
  margin-left: 50px;
}
p.quote {
  margin-left: 50px;
  border: 2px solid black;
  background-color: #f0f0e0;
}
table {
  border: 1px solid black;
  border-collapse: collapse;
  margin-left: auto;
  margin-right: auto;
  margin-top: 0.8em;
  text-align: left;
  hyphens: none; 
}
td, th {
  padding-left: 1em;
  padding-right: 1em;
  vertical-align: top;
}
th {
  border-bottom: 2px solid black;
  background-color: #f0f0f0;
}
</style>
</head>
<body>
<h1 class="title" style="text-align:center">C++ contracts with regards to function pointers</h1><table><tbody><tr><td> Document number </td><td> D3250R1 </td></tr><tr><td> Date </td><td> 2024-04-22 </td></tr><tr><td> Reply-to </td><td> Peter Bindels &lt;dascandy@gmail.com&gt; </td></tr><tr><td> Targeted subgroups </td><td> SG21 </td></tr></tbody></table><h1 data-number="1" id="Introduction"><span class="header-section-number">1</span> Introduction<a href="#Introduction" class="self-link"></a></h1><p>The current papers on contracts <a title="P2899" href="#ref-1">[1]</a>, <a title="P2900" href="#ref-2">[2]</a> discuss in detail how the contracts facility inside C++ should work, with the perspective of having a future C++ standard version, and how a code base composed solely of C++26+ code using contracts will work. In this paper, I will be exploring the space where languages meet - both non-C++ languages and codebases written in and compatible with prior revisions of C++. With the approach outlined in this paper, libraries can be used from older c++ code bases, C code bases and other languages with less boilerplate and in many cases without any breaking changes, while still being able to assert contracts on their interface.</p><p>This paper constitutes a breaking change on the current MVP as it changes the behavior of function pointer conversion. Specifically, it advocates to make function pointer conversion in a deduced context ill-formed, to reserve this space for a future function-pointers-with-contracts feature. The paper assumes familiarity with P2900.</p><h1 data-number="2" id="Revision-history"><span class="header-section-number">2</span> Revision history<a href="#Revision-history" class="self-link"></a></h1><p>R1: Remove discussion on implementation strategy and move to separate paper, focusing this paper on only whether or not a function can be deduced as a function pointer / whether to reserve space for function pointers with contracts.</p><h1 data-number="3" id="Contracts-and-function-pointers"><span class="header-section-number">3</span> Contracts and function pointers<a href="#Contracts-and-function-pointers" class="self-link"></a></h1><p>P2900 leaves open the question whether contracts are checked on the caller side or the callee side. This mostly works (see other paper P33xX for a treatise on implementation details), except for the case of function pointers.</p><p>A function pointer is the address of a function, stored as an assignable value. In P2900 so far, a function pointer cannot have contracts specified on them. This restriction initially follows from the idea to make an MVP, and function pointers tread into conversion rules between different sets of contracts, making the current solution a good stopgap for the MVP. This does imply that if a function is invoked through a function pointer, for the contracts to have any effect, they necessarily must be checked callee-side.</p><p>Having the check callee-side prevents compilers from entering the function without a callee-side contract check, and prevents compilers from optimizing away such a contract check (for example, if the assertions are provable for the compiler implementation based on the code preceding the function pointer call).</p><h1 data-number="4" id="Benefits-of-reserving-space-for-contracts-on-function-pointers"><span class="header-section-number">4</span> Benefits of reserving space for contracts on function pointers<a href="#Benefits-of-reserving-space-for-contracts-on-function-pointers" class="self-link"></a></h1><ul><li>Being able to annotate a function pointer with a contract would allow a compiler to enter the pointed-to function without doing callee-side checks, and use the same contract annotations to do (or elide) those checks caller-side. Contracts being elided by proof in compilers is a very strong driving force behind wide adoption of contracts to write performant safe code.</li><li>Future contracts on function pointers enable function pointer conversion between different sets of contracts (for example, from a more restrictive to a less restrictive, allowing a function to remain annotated by the stronger contract while being used with a weaker contract).</li><li>The proposed method of reserving space for function-pointers-with-contracts preserves the ability to use function pointers, which is a very important part of interacting with different APIs, such as std::function, and many C-style libraries. </li></ul><h1 data-number="5" id="Downsides-of-reserving-space-for-contracts-on-function-pointers"><span class="header-section-number">5</span> Downsides of reserving space for contracts on function pointers<a href="#Downsides-of-reserving-space-for-contracts-on-function-pointers" class="self-link"></a></h1><ul><li>The address-of operator for a function name would not be implicitly convertible to a function pointer, but only explicitly. Functions cannot then easily be used in a place where their type would be deduced. This means that assigning it to an <span class="code">auto*</span> variable will fail to compile, as will use of a function with contracts being passed into a template. This is circumventable with an operator like <span class="code">operator+(&lt;overload set&gt;)</span>, which would take the raw function pointer with contract checks (if applicable), but that would be a change to the current proposal too. As the syntax used is the logical syntax for deducing a function pointer-with-contracts, leaving this working will necessarily remove our ability to give that meaning to this construct.</li><li>The space reserved this way for function pointers with contracts may not be a usable space. In P2900 we do make a choice to make contracts not a visible property to reflection, and if function pointers are not trivially assignable and convertible (ie, the restriction suggested above) that is detectable and usable from other functions, metafunctions and reflection to determine whether something has contracts, counter to the direction so far.</li></ul><h1 data-number="6" id="Changes-to-P2900"><span class="header-section-number">6</span> Changes to P2900<a href="#Changes-to-P2900" class="self-link"></a></h1><p>Change in 3.3.5:</p><p>    </p><p>    The contract assertions on a function have no impact on its type<span class="delete"> and thus no impact on the type of its address, nor on what types of function pointers that address may be assigned to:</span><span class="new">. The address of a function with contracts is treated as an overload set, making it ambiguous in a deduced context, and selecting the non-contract version in case of a conversion to a type compatible with it.</span></p><p>Add to the code example:</p><code><div class="code">
using function_type = int(*)(int);
auto *fp2 = f; // ERROR
auto *fp3 = (function_type)f; // OK

template &lt;typename FT&gt;
void g(FT func);
g(f); // ERROR
g((function_type)f); // OK</div></code><h1 data-number="7" id="Acknowledgements"><span class="header-section-number">7</span> Acknowledgements<a href="#Acknowledgements" class="self-link"></a></h1><p>Major thanks to all of SG21 for the work done on contracts so far; this paper would not be possible without a very well formed P2900 to write it against.</p><p>Thanks to Jonas Persson for writing P3221, which provided the direct impetus to write this paper, in a hope to have more C, legacy C++ and other-language compatibility in the MVP at a very minor cost.</p><p>Thanks to Corentin Jabot, Miro Knejp, Dawid Pilarski and Tom Honermann for reviewing this paper before publishing, and pointing out some confusing errors before publishing.</p><p>Thanks to Ville Voutilainen, Lisa Lippincott and others for additional information during discussions which helped shape the paper into better illuminating both sides of the argument.</p><h1 data-number="8" id="References"><span class="header-section-number">8</span> References<a href="#References" class="self-link"></a></h1><ol><li id="#ref-1"><a href="http://wg21.link/p2899">P2899 (http://wg21.link/p2899)</a></li><li id="#ref-2"><a href="http://wg21.link/p2900">P2900 (http://wg21.link/p2900)</a></li></ol></body></html>
