
<?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/MarkUp/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<style type="text/css">/*<![CDATA[*/

body { color: #000000; background-color: #FFFFFF; }
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; }

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.5empadding-right: 0.5em; ; }

blockquote.stdins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3; padding: 0.5em; }

blockquote pre em { font-family: 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.8em; border: none; }
td { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }

/*]]>*/
</style>

<title>Regular Void</title>
</head>
<body>

<p style="text-align: right; float: right">
ISO/IEC JTC1 SC22 WG21<br />
P0146R0<br />
Project: Programming Language C++, Evolution Working Group<br />
Matt Calabrese (<a href="mailto:metaprogrammingtheworld@gmail.com">metaprogrammingtheworld@gmail.com</a>)<br />
2015-09-25<br />
</p>

<h1>Regular Void</h1>

<h2><a id="Abstract">Abstract</a></h2>
<p>This paper evaluates the current specification of <code>void</code> in C++ as an incomplete type with exceptional rules and proposes changes that would update <code>void</code> to instead be a complete, object type. The intent of this modification is to eliminate special casing in generic code where <code>void</code> may appear as a dependent type, such as the existing <code>std::promise&lt;void&gt;</code> specialization in the standard library, and to do so in a way that minimizes breakage of existing code. This also has the positive side-effect of simplifying the standard as a whole, due to the amendment or outright removal of several clauses that currently need to treat void separately and explicitly.</p>

<h2><a id="Motivation">Motivation</a></h2>

<p>One of the many poweful aspects of C++ is its ability to represent generic functions and types as exemplified by the algorithms and containers of the standard library, which are able to operate on built-in and user-defined types equivalently provided that the types involved model the necessary concepts. One of the underlying properties of the language that makes this feasible is the potential for user-defined types to behave in both a syntactically and semantically similar manner to built-in types. This is because the language gives built-in object types and user-defined types value semantics, and allows for overloading and generic functions by way of templates. In practice this usually works well, however, <code>void</code> types often pose difficulty in generic code because they are incomplete and not instantiable, even though they can be appear as the result type of a function that may be invoked in a generic setting. They are very unique with respect to built-in types, let alone user-defined ones.</p>

<p>Consider the following example, based on real-world code:</p>

<pre style='color:#000000;background:#ffffff;'><span style='color:#696969; '>// Invoke a callable, logging its arguments and return value.</span>
<span style='color:#800000; font-weight:bold; '>template</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> R<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> P<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Callable<span style='color:#800080; '>></span>
R invoke_and_log<span style='color:#808030; '>(</span>callable_log<span style='color:#808030; '>&lt;</span>R<span style='color:#808030; '>(</span>P<span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>)</span><span style='color:#808030; '>></span><span style='color:#808030; '>&amp;</span> <span style='color:#603000; '>log</span><span style='color:#808030; '>,</span> Callable<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> callable<span style='color:#808030; '>,</span> P<span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> args<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
  log<span style='color:#808030; '>.</span>log_arguments<span style='color:#808030; '>(</span>args<span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800000; font-weight:bold; '>auto</span> result <span style='color:#808030; '>=</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>invoke<span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Callable<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>callable<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span>
                            <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>P<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>args<span style='color:#808030; '>)</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  log<span style='color:#808030; '>.</span>log_result<span style='color:#808030; '>(</span>result<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800000; font-weight:bold; '>return</span> result<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>
</pre>

<p>The above code is simple enough, however, it breaks down in one, very important case -- when the return type of the <code>Callable</code> happens to be <code>void</code> (there is another class of cases not handled here, though this is to keep the example simple). In the <code>void</code> case, we'd still expect <code>callable</code> to be invoked and to have its arguments logged. Perhaps more subtle, the call to <code>log.log_result(result)</code> is meaningful even if serialization of a <code>void</code> were to end up being a no-op, since the invocation of the function still signals a successful execution of <code>callable</code> (i.e. if we get there, <code>std::invoke</code> did not propagate an exception). Ideally, all of this code would just work as written and without further specialization or indirection to account for the case where <code>callable</code> returns <code>void</code>.</p>

<h3><a id="StandardExample">Example in the Standard</a></h3>

<p>The motivation for this change does not exist solely in user-written generic code, as symptoms of the underlying problem are visible even in the standard libary itself. Most cleary, this can be seen with the need for specializations of <code>std::promise</code> and <code>std::future</code> for the <code>void</code> type. It can further be seen in proposals such as the <code>void</code> specialization for the <code>expected</code> template<sup><a href="#References_Expected">2</a></sup>. Unfortunately, even though we already have specializations for <code>std::promise</code> that at least allow <code>std::promise&lt;void&gt;</code> to be created, dealing with that type in generic code by users is still difficult due to the way that <code>void</code> is handled in the language and the fact that the specializations provide no common interface for setting the promised value (this latter point does not actually have to be the case even without changes to the language itself, though such an interface would be less than ideal). An example of where things break down in simple generic code that deals with <code>std::promise</code> can be seen here:</p>

<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>template</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> T<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>void</span> set_value_with_result<span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>promise<span style='color:#800080; '>&lt;</span>T<span style='color:#800080; '>></span><span style='color:#808030; '>&amp;</span> p<span style='color:#808030; '>,</span> Fun fun<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
  p<span style='color:#808030; '>.</span>set_value<span style='color:#808030; '>(</span>fun<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>
</pre>

In the above code, if <code>T</code> happens to be <code>void</code>, our code will fail because <code>set_value</code> in that case takes no parameters other than the promise itself, and you also cannot pass a void expression as a function argument.

<p><i>Note: This paper strictly addresses language changes to <code>void</code> without proposing significant changes to the standard library. If the language changes are considered viable, a separate proposal is planned that would specify updates to the standard library, such as the removal of the <code>void</code> specializations of <code>std::promise</code> and <code>std::future</code> in a way that would be relatively seamless for existing users.</i></p>

<h2><a id="ProblemDesc">Problem Description</a></h2>

<p>Generic programming in C++ is especially powerful because with care, concept requirements can usually be specified in a way such that they may be met nonintrusively with respect to an existing type, making it possible to have the type model a concept even if a programmer otherwise has no control over its implementation (i.e. it is a part of a dependency or is a built-in type). However, sometimes requirements are specified that simply cannot be met nonintrusively. A good example of this is when a type requirement is the instantiability of that type, or proper semantics regarding special member functions. In these cases, if the type does not already meet these requirements, they cannot be met without modifying the type in question. If the type in question is a part of a dependency or happens to be a fundamental type of the language, then that type cannot be made to model the given concept without either patching the dependency or changing the language, respectively. This is particularly unfortunate if a type <i>could</i> model the concept without any cost, yet simply does not do so.</p>

<p>The problem that generic libraries face when dealing with <code>void</code> can be thought of as precisely this last case. As currently specified in the language, <code>void</code> cannot be instantiated, nor can it be copied or compared, even though it can be logically thought of as a monostate type.</p>

<h2><a id="RecommendedSolution">Recommended Solution</a></h2>

<p>Briefly, the solution that is recommended by this proposal is to change <code>void</code> to a complete object type and to do so in a way that prevents considerable breakage to existing code. This also implies that <code>void</code> can appear as a function parameter, that you can form references to <code>void</code>, and that you can do anything else that is expected of other object types. Although this change may sound risky, the alterations are specified in such a way that potential breakage is limited. Descriptions of potential breaking cases are detailed later.</p>

<p>In reality, it is more likely that this change could be made in such a way that most existing users of the language would not even notice the update, and their code would not be affected adversely by such ignorance. What is proposed more formally below is a fairly straight-forward simplification to the standard, removing many parts that currently need to explicitly mention <code>void</code> types in wording due to their nature as a unique kind of type in C++. The most risky of changes are discuessed in this documently explicitly, separate from the actual changes that are suggested for the standard.</p>

<h3><a id="Considerations">Considerations</a></h3>

<h4><a id="UnaryVoid">Unary Functions Taking Void</a></h4>

<p>As <code>void</code> becomes a <code>Regular</code><sup><a href="#References_FoGP">1</a></sup> type, it is essential that it is allowed as function paramter types, just like any other object type in the language, otherwise it is not suitable in generic code, as seen in the logging and <code>std::promise</code> examples. This, however, brings about one minor, though unfortunate problem. Syntactically, in current C++, a type such as <code>int(void)</code> is valid yet is not a function taking <code>void</code> as a parameter, but rather, it is a function taking no parameters. In other words, even though it is syntactically different, it specifies the same type as <code>int()</code>. This is, perhaps, obvious, but it means that we would not be able to reclaim that syntax without causing a large amount of breaks to existing code. What's worse is that sometimes those breaks could hypothetically cause compilation or linking to still succeed, but have different results.</p>

<p>The suggested solution to this problem is to not reclaim this syntax, at least not at this time, when the <code>void</code> type is not dependent. Whether or not the syntax should be deprecated for future reclamation is questionable, though it is recommended in this proposal that we do so. Importantly, we can and should use this syntax when <code>void</code> is dependent, as is explicitly suggested in this proposal, and is thankfully not allowed in the present state of the language. Because it is not allowed currently, it is less likely (though still possible in hypothetical cases) that such a change would break existing code. The reason why it is important that we allow this syntax in a dependent context is because this is precisely where it matters to generic code. By utilizing the syntax in this context, we have little-to-no chance of breaking any existing code while also allowing for generic code to be written in a way that does not need to specialize or go through indirection in the event that <code>void</code> happens to show up as a dependent type.</p>

<p>This leaves us with one question, though. If, when in a non-dependent context, you cannot declare a function that takes a single, <code>void</code> parameter using this syntax, how exactly would you specify such a function type? There are multiple options, but ultimately it is recommended that users either specify the <code>void</code> parameter type with cv-qualification, which is not valid in this context in current C++, or alternatively they can simply give the parameter a name, which is also not currently allowed. Both of these solutions are specified as a part of this proposal. Rationale for why this seemingly subtle syntax is the prefered solution is presented later.</p>

<p>Finally, it deserves to be repeated that this quirkiness is only required when the function in question takes exactly one parameter, where that parameter is <code>void</code>, and where that <code>void</code> is not a dependent type. If the function type takes multiple parameters, then the user needs to do nothing special. Similarly, if the <code>void</code> type is dependent, the user also needs to do nothing special. This only would affect a small amount of yet-to-be-written code that only a certain class of users would ever want to write, and it does not at all negatively affect the simplicity of writing generic code.

<h4><a id="Linking Breakages">Linking Breakages</a></h4>

<p>Because we are changing the <code>void</code> type, it might initially seem as though we'd, in practice, be breaking compatibility with existing, prebuilt libraries, including C libraries, and thereby force them to no longer link correctly. This is actually untrue. Since our alterations do not add any state to the <code>void</code> type, no additional or different information needs to be communicated, and in practice, implementations would be able to retain compatibility.</p>

<h4><a id="SFINAE">SFINAE</a></h4>

<p>While mostly theoretical, there are potentially SFINAE exploits that might be in use that could take advantage of <code>void</code>'s properties, such as its inability to be used as a function parameter type in a dependent context, and its inability to be used in a <code>sizeof</code> expression. At the very least, such exploits are not known to have been used in standard library implementations nor have they been encouraged in Boost. It is suspected that such properties are exploited rarely, if it all, and in those few cases if and where they are exploited, there already exist drop-in alternatives via other forms of SFINAE exploits. Note that the <code>sizeof</code> trick that is or was frequently used when defining metafunction traits is distinct from what is described here and would not be affected.</p>

<h4><a id="Ternary">Ternary Operator</a></h4>

<p>While most of the changes proposed are simple, there is one somewhat non-trivial change made to the ternary operator. This should be examined more closely to be certain that there is no adverse effect by this change. An implementation is not provided along with this proposal.</p>

<h2><a id="Alternatives">Alternatives</a></h2>

<p>The solution that is proposed was arrived at after carefully considering possible alternatives. Notable suggestions from other parties are presented below.

<h3><a id="LibraryBasedSolutions">Library-Based Solutions</a></h3>

<p>As described in the motivation section, the current way that generic code deals with <code>void</code> is by special-casing code, often through helper templates. It has been suggested that we instead possibly consider standardizing helper templates that ease dealing with <code>void</code> in generic code. The problems with this are that such facilities would be both complicated to specify correctly and would require people writing generic code to actually know about and use them. When and why it would be important is subtle, and we'd likely not be able to cover all cases. Readers of that code who are not familiar with the problem would also be baffled by the subtleties (a problem that already exists today when writing such generic code, which a change to <code>void</code> would remedy). By simply making <code>void</code> an object type, we solve our problems completely and in a way that is easy for users to utilize and also easier to specify fully and properly in the standard when compared to a complicated set of library facilities.</p>

<h3><a id="PartialVoid">Void as <i>Almost</i> an Object</a></h3>

<p>The idea here is that instead of making <code>void</code> an object type, we instead just make it act a little bit like one in certain contexts. The proclaimed rationale for this approach is that we introduce fewer changes to the meaning of <code>void</code> so as to minimize breakages and to not make <code>void</code> do more than is necessary. For instance, it was suggested that we make it possible to create an instance of <code>void</code> on the stack, but not be able to pass it to a function as an argument, or make an array or tuple that contains a <code>void</code> element. While the intention here is in the right place, the rationale is flawed in several ways:
<ul>
  <li>By just making <code>void</code> <i>almost</i> an object, we'd only be trading some special-casing in generic code for other special-casing.</li>
  <li>The changes to the standard that would make <code>void</code> an object are simpler to specify than trying to make <code>void</code> <i>almost</i> an object type with special rules.</li>
  <li>All of the functionality of a <code>Regular</code> type really is required since things like function result types are often worked with in this manner in generic code.</li>
  <li>There is no evidence that an intermediate step in the re-specification of <code>void</code> as an object type would at all reduce breakage to existing code when compared to making the full change. It could, however, scatter the complete changes across multiple standards, leaving the language with unnecessarily subtle differences between iterations.</li>
</ul>

</p>

<h3><a id="NewVoid">An Entirely New Void Type</a></h3>

<p>Also suggested was the possibility of introducing a new type to the language, separate from <code>void</code>, that behaves in the way that this proposal specifies the existing <code>void</code> type should behave. The idea of this solution is that people who want such a monostate type can opt-in for it, leaving the existing <code>void</code> type unchanged. This initially may seem like a reasonable solution, but it fails to actually solve the generic programming problem since <i>users</i> of the generic code would be the ones who would be required to now take advantage of that new type. Library developers would still need to special-case for <code>void</code> in practice because of this.</p>

<h3><a id="ExplicitVoid">Explicit Void</a></h3>
<p>As described earlier, this proposal recommends using <i>cv-void</i> or a named <code>void</code> parameter for representing a unary function with a <code>void</code> parameter when <code>void</code> is not dependent. One alternative to using <i>cv-void</i> or a named <code>void</code> parameter for representing a unary function having a <code>void</code> parameter is to instead propose an entirely new syntax for that case. For instance, one possiblity is to allow a declaration such as:
<pre><code>void foo(explicit void) {}</code></pre>
</p>

<p>At first this may seem like a good idea since it makes the difference between it and the current meaning of a <code>void</code> parameter list more drastic, however it has a few drawbacks:
<ul>
  <li>It introduces a syntax that would only work for <code>void</code> (unless it were also proposed to work for other types for the sake of consistency).</li>
  <li>It is a more complex change as it requires altering the language grammar.</li>
  <li>It introduces a syntax that would likely be deprecated in the future.</li>
</ul>
</p>

<p>The last point is a bit subtle, though it may be the most important. Ultimately, in a future standard it would be a simplification to the langauge to make a parameter-list consisting of a single, unnamed, cv-unqualified <code>void</code> parameter behave no different from most other object types. That is to say, that syntax would eventually be used to declare a unary function taking a parameter of type <code>void</code>. It is not recommended that we update the meaning of that syntax immediately as a part of this proposal because that would change the meaning of a large body of existing code in a way that would cause breakages, including sometimes in ways that only change behavior of existing programs at runtime. By at most deprecating the current meaning of <code>void</code> in a parameter list, we'd effectively provide a buffer for existing code to be updated such that the further update can potentially take place in some future standard. If, in the meantime, we were to introduce an entirely new syntax and alter the language grammar solely to allow the declaration of a parameter of type <code>void</code>, we'd likely want to eventually deprecate and remove <i>that</i> syntax once the desired syntax is ripe to be used. On the other hand, if in the time being we only use cv-qualified <code>void</code> or a named <code>void</code> parameter to represent an actual <code>void</code> parameter, then if/when the current meaning of <code>void</code> is to finally be replaced, any code that declared a single parameter of type <code>void</code> in the currently proposed manner would not need to be updated, since even then it would remain as a valid way to declare such a parameter (just as it is a valid way in the language right now to declare parameters of non-<code>void</code> type).</p>

<p>So, at the cost of being a little bit subtle in newly-written code, we avoid cluttering the language with new syntax and also avoid having to remove a special syntax at some point in the future. It is a simpler change in the language to make right now, in addition to being better in the long term.</p>

<h3><a id="ParameterCollapsing">Parameter Collapsing</a></h3>

<p>In discussions, it has been suggested by multiple parties independently to consider "collapsing" <code>void</code> parameters in a function type in a way that makes a function type specified as <code>void (int, void)</code> equivalent to the function type <code>void (int)</code>. Similarly, when invoking a function and passing a <code>void</code> expression as an argument, that argument would instead be ignored and the invocation would actually be passing one less argument than it would appear. Though intially this might not look problematic, not only does it keep <code>void</code> as a special type with special rules that can really make it difficult to write certain generic code, but it also introduces subtle ambiguities or other errors. For example:</p>

<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>enum</span> <span style='color:#800000; font-weight:bold; '>class</span> log_option <span style='color:#800080; '>{</span> simple<span style='color:#808030; '>,</span> verbose <span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#800000; font-weight:bold; '>template</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> T<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>void</span> <span style='color:#603000; '>log</span><span style='color:#808030; '>(</span>T what_to_log<span style='color:#808030; '>,</span> log_option option <span style='color:#808030; '>=</span> log_option<span style='color:#800080; '>::</span>simple<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>

<span style='color:#800000; font-weight:bold; '>template</span><span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>void</span> log_result<span style='color:#808030; '>(</span>Fun fun<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
  <span style='color:#603000; '>log</span><span style='color:#808030; '>(</span>fun<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> log_option<span style='color:#800080; '>::</span>verbose<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>

<span style='color:#800000; font-weight:bold; '>int</span> <span style='color:#400000; '>main</span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
  <span style='color:#696969; '>// logs an int using the verbose option</span>
  log_result<span style='color:#808030; '>(</span><span style='color:#808030; '>[</span><span style='color:#808030; '>]{</span> <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#008c00; '>0</span><span style='color:#800080; '>; }</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>

  <span style='color:#696969; '>// If internally the first argument "collapses" because the function returns void,</span>
  <span style='color:#696969; '>// then we are no longer logging "void" with the "verbose" option, but instead,</span>
  <span style='color:#696969; '>// we are logging an instance of "log_option" with the "simple" option.</span>
  log_result<span style='color:#808030; '>(</span><span style='color:#808030; '>[</span><span style='color:#808030; '>]{}</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>
</pre>

<h3><a id="SizeZero">Size Zero Void</a></h3>

<p>One suggestion that has repeatedly come up is to have <code>sizeof(void)</code> report <code>0</code> and to allow multiple instances to share the same address. This would prevent users from having to use tricks akin to the empty base optimization in order to make more optimal usage of memory. Ideally, this would be the case, however such a change to the language is both vast and out of scope of the proposal. Allowing a type to have a <code>0</code> size and to allow separate instances to share an address implies drastic and subtle breaking changes to existing code. For instance, if you were to make an array of such a <code>void</code> type, a pointer, at least in the traditional sense, would no longer be able to be used as an iterator into that array (notably meaning that generic code which relies on this would now fail for such a size <code>0</code> type). As well, any code that relies on an object's type and address as unique would fail for <code>void</code> types, even though it is otherwise perfectly acceptable. Finally, if such a size were permitted for <code>void</code>, it should really be allowed for <code>any</code> type, including user-defined types. Having a special rule for <code>void</code> would make one more thing to have to think about and deal with differently for <code>void</code> types. Instead, this proposal opts to leave the size of <code>void</code> unspecified and thereby governed by existing language rules. In practice, it is expected that <code>void</code> will likely be size <code>1</code> in most implementations, though this is not required. If an eventual change were made to the language to allow for size <code>0</code> types, then <code>void</code> would be able to implicitly take advantage of that.</p>

<h2><a id="Proposal">Proposed solution</a></h2>
<p>The <code>void</code> type is updated to be an object type with care taken to minimize breaking changes to existing code. This implies a considerable number of changes to the standard, although most of those changes are simplifications due to the removal of redundant statements mentioning <code>void</code>, which are now implicitly covered by the fact that <code>void</code> is a complete object type that is considered a scalar. Additional updates are planned for the LEWG, such as updates to <code>std::promise</code>, but they are outside of the scope of this proposal and are predicated on the viability of the language changes presented here.</p>

<p>Change in §3.9 [basic.types] paragraph 5:
<blockquote class="std">
A class that has been declared but not defined, an enumeration type in certain contexts (7.2), or an array of
unknown size or of incomplete element type, is an incompletely-defined object type. Incompletely-defined
object types <del>and the void types</del> are incomplete types (3.9.1). Objects shall not be defined to have an
incomplete type.
</blockquote></p>

<p>Change in §3.9 [basic.types] paragraph 8:
<blockquote class="std">
An object type is a (possibly cv-qualified) type that is not a function type<del>,</del> <ins>and</ins> not a reference type<del>, and not a
void type</del>.
</blockquote></p>

<p>Change in §3.9 [basic.types] paragraph 9:
<blockquote class="std">
Arithmetic types (3.9.1), enumeration types, <ins>void types,</ins> pointer types, pointer to member types (3.9.2), std::nullptr_t, and cv-qualified versions of these types (3.9.3) are collectively called <i>scalar types</i>.
</blockquote></p>

<p>Remove §3.9 [basic.types] paragraph 10.1 (regarding what is a literal type, remove redundancy now that void is a scalar type):
<blockquote class="stddel">
— possibly cv-qualified void; or
</blockquote></p>

<p>Change in §3.9.1 [basic.fundamental] paragraph 9:
<blockquote class="std">
The void type has <del>an empty set</del> <ins>a unit set</ins> of values. <del>The void type is an incomplete type that cannot be completed. It
is used as the return type for functions that do not return a value.</del> Any expression can be explicitly converted
to type cv void (5.4). <del>An expression of type void shall be used only as an expression statement (6.2), as an
operand of a comma expression (5.19), as a second or third operand of ?: (5.16), as the operand of typeid,
noexcept, or decltype, as the expression in a return statement (6.6.3) for a function with the return type
void, or as the operand of an explicit conversion to type cv void.</del>
</blockquote></p>

<p>Change in §3.9.2 [basic.compound] paragraph 1.2 (regarding how compound types can be constructed, remove redundancy now that void is an object type):
<blockquote class="std">
— <i>functions</i>, which have parameters of given types and return <del>void or</del> references or objects of a given
type, 8.3.5;
</blockquote></p>

<p>Change in §3.9.2 [basic.compound] paragraph 1.3 (regarding how compound types can be constructed, remove redundancy now that void is an object type):
<blockquote class="std">
— <i>pointers</i> to <del>void or</del> objects or functions (including static members of classes) of a given type, 8.3.1;
</blockquote></p>

<p>Change in §3.9.2 [basic.compound] paragraph 3:
<blockquote class="std">
The type of a <del>pointer to void or a</del> pointer to an object type is called an <i>object pointer type</i>. <del>[ <i>Note</i>: A pointer
to void does not have a pointer-to-object type, however, because void is not an object type. — <i>end note</i> ]</del>&hellip;
</blockquote></p>

<p>Change in §3.9.3 [basic.type.qualifier] paragraph 1 (remove redundancy now that void is an object type):
<blockquote class="std">
A type mentioned in 3.9.1 and 3.9.2 is a <i>cv-unqualified type</i>. Each type which is a <i>cv-unqualified</i> complete
or incomplete object type <del>or is void (3.9)</del> has three corresponding cv-qualified versions of its type: a <i>const-qualified</i>
version, a <i>volatile-qualified</i> version, and a <i>const-volatile-qualified version</i>. The term object type (1.8)
includes the cv-qualifiers specified in the decl-specifier-seq (7.1), declarator (Clause 8), type-id (8.1), or newtype-id
(5.3.4) when the object is created.
</blockquote></p>

<p>Change in §3.10 [basic.lval] paragraph 4 (remove redundancy now that void is complete type):
<blockquote class="std">
Unless otherwise indicated (5.2.2), prvalues shall always have complete types <del>or the void type</del>; in addition to
these types, glvalues can also have incomplete types. [ <i>Note</i>: class and array prvalues can have cv-qualified
types; other prvalues always have cv-unqualified types. See Clause 5. — <i>end note</i> ]
</blockquote></p>

<p>Change in §5.2.2 [expr.call] paragraph 3 (remove redundancy now that void is an object type):
<blockquote class="std">
If the <i>postfix-expression</i> designates a destructor (12.4), the type of the function call expression is void;
otherwise, the type of the function call expression is the return type of the statically chosen function (i.e.,
ignoring the virtual keyword), even if the type of the function actually called is different. This return type
shall be an object type<del>,</del> <ins>or</ins> a reference type <del>or cv void</del>.
</blockquote></p>

<p>Change in §5.2.3 [expr.type.conv] paragraph 2 (initialization now covered by value-initializing since void is an object type):
<blockquote class="std">
The expression T(), where T is a <i>simple-type-specifier</i> or <i>typename-specifier</i> for a non-array complete object
type <del>or the (possibly cv-qualified) void type</del>, creates a prvalue of the specified type, whose value is that
produced by value-initializing (8.5) an object of type T<del>; no initialization is done for the void() case</del>. [ <i>Note</i>:
if T is a non-class type that is cv-qualified, the cv-qualifiers are discarded when determining the type of the
resulting prvalue (Clause 5). — <i>end note</i> ]
</blockquote></p>

<p>Change in §5.3.1 [expr.unary.op] paragraph 1 (void is no longer incomplete):
<blockquote class="std">
The unary * operator performs indirection: the expression to which it is applied shall be a pointer to an
object type, or a pointer to a function type and the result is an lvalue referring to the object or function
to which the expression points. If the type of the expression is “pointer to T”, the type of the result is
“T”. [ <i>Note</i>: indirection through a pointer to an incomplete type <del>(other than cv void)</del> is valid. The lvalue
thus obtained can be used in limited ways (to initialize a reference, for example); this lvalue must not be
converted to a prvalue, see 4.1. — <i>end note</i> ]
</blockquote></p>

<p>Remove §5.3.5 [expr.delete] footnote 80:
<blockquote class="stddel">
This implies that an object cannot be deleted using a pointer of type void* because void is not an object type
</blockquote></p>

<p>Change in §5.9 [expr.rel] paragraph 1:
<blockquote class="std">
&hellip;
The operands shall have arithmetic, enumeration, <ins>void,</ins> or pointer type. The operators &lt; (less than), &gt; (greater
than), &lt;= (less than or equal to), and &gt;= (greater than or equal to) all yield false or true. The type of the
result is bool.
</blockquote></p>

<p>Change in §5.10 [expr.eq] paragraph 1:
<blockquote class="std">
The == (equal to) and the != (not equal to) operators group left-to-right. The operands shall have arithmetic,
enumeration, <ins>void,</ins> pointer, or pointer to member type, or type std::nullptr_t. The operators == and != both
yield true or false, i.e., a result of type bool. In each case below, the operands shall have the same type
after the specified conversions have been applied.
</blockquote></p>

<p>Add new paragraph to §5.10 [expr.eq]:</p>
<blockquote class="stdins">
Two operands of type void compare equal.
</blockquote></p>

<p>Change in §5.16 [expr.cond] paragraph 2 (regarding the conditional operator):</p>
<blockquote class="std">
If either the second or the third operand <del>has type void</del> <ins>is a (possibly parenthesized) throw-expression (5.17)</ins>, one of the following shall hold:<br />
(2.1) — The second or the third operand (but not both) is a (possibly parenthesized) throw-expression <del>(5.17)</del>;
the result is of the type and value category of the other. The conditional-expression is a bit-field if
that operand is a bit-field.<br />
(2.2) — Both the second and the third operands <del>have type void</del> <ins>are a (possibly parenthesized) throw-expression</ins>; the result is of type void and is a prvalue.
<del>[ <i>Note</i>: This includes the case where both operands are throw-expressions. — <i>end note</i> ]</del>
</blockquote></p>

<p>Change in §6.6.3 [stmt.return] paragraph 2:
<blockquote class="std">
The expression or braced-init-list of a return statement is called its operand. A return statement with
no operand shall be used only in a function whose return type is cv void, a constructor (12.1), or a
destructor (12.4). <del>A return statement with an operand of type void shall be used only in a function whose
return type is cv void. A return statement with any other operand shall be used only in a function whose
return type is not cv void; the</del><ins>A</ins> return statement with <del>any other</del> <ins>an</ins> operand initializes the object or reference to be returned by <i>copy-initialization</i>
(8.5) from the operand. [ <i>Note</i>: A return statement can involve the construction and copy or
move of a temporary object (12.2). A copy or move operation associated with a return statement may be
elided or considered as an rvalue for the purpose of overload resolution in selecting a constructor (12.8).
— <i>end note</i> ]  [<i>Example</i>:
<pre>std::pair&lt;std::string,int&gt; f(const char* p, int x) {
  return {p,x};
}</pre>— end example ]
</blockquote></p>

<p>Change in §8.3.2 [dcl.ref] paragraph 1.
Remove the final statement starting after the end of the last note:
<blockquote class="stddel">
A declarator that specifies the type “reference to cv void” is ill-formed.
</blockquote></p>

<p>Change in §8.3.3 [dcl.mptr] paragraph 3:
<blockquote class="std">
A pointer to member shall not point to a static member of a class (9.4)<del>,</del> <ins>or</ins> a member with reference type<del>, or
“cv void”</del>.<br />
[ <i>Note</i>: See also 5.3 and 5.5. The type “pointer to member” is distinct from the type “pointer”, that is, a
pointer to member is declared only by the pointer to member declarator syntax, and never by the pointer
declarator syntax. There is no “reference-to-member” type in C++. — <i>end note</i> ]
</blockquote></p>

<p>Change in §8.3.4 [dcl.array] paragraph 1:
<blockquote class="std">
&hellip;
T is called the array element type; this type shall not be a reference type, <del>the (possibly <i>cv</i>-qualified)
type void,</del> a function type or an abstract class type.
&hellip;
</blockquote></p>

<p>Change in §8.3.4 [dcl.array] paragraph 2:
<blockquote class="std">
An array can be constructed from one of the fundamental types <del>(except void)</del>, from a pointer, from a pointer
to member, from a class, from an enumeration type, or from another array.
</blockquote></p>

<p>Change in §8.3.5 [dcl.fct] paragraph 4:
<blockquote class="std">
The <i>parameter-declaration-clause</i> determines the arguments that can be specified, and their processing, when
the function is called. [ <i>Note</i>: the <i>parameter-declaration-clause</i> is used to convert the arguments specified
on the function call; see 5.2.2. — <i>end note</i> ] If the <i>parameter-declaration-clause</i> is empty, the function takes
no arguments. A parameter list consisting of a single unnamed parameter of non-dependent type void is
equivalent to an empty parameter list <ins>[ <i>Note</i>: This usage of void is deprecated. — <i>end note</i> ]</ins>.
<del>Except for this special case, a parameter shall not have type cv void.</del>
<ins>This is the only case for which a parameter of type cv void has special meaning.</ins>
If the <i>parameter-declaration-clause</i> terminates with an ellipsis or a function parameter pack (14.5.3), the
number of arguments shall be equal to or greater than the number of parameters that do not have a default
argument and are not function parameter packs. Where syntactically correct and where “...” is not part
of an abstract-declarator, “, ...” is synonymous with “...”. [<i>Example</i>: the declaration
<pre>	int printf(const char*, ...);</pre>
declares a function that can be called with varying numbers and types of arguments.
<pre>	printf("hello world");
	printf("a=%d b=%d", a, b);</pre>
However, the first argument must be of a type that can be converted to a const char* — end example ]
[ <i>Note</i>: The standard header &lt;cstdarg&gt; contains a mechanism for accessing arguments passed using the
ellipsis (see 5.2.2 and 18.10). — <i>end note</i> ]
</blockquote></p>

<p>Change in §9.4.2 [class.static.data] paragraph 2 (void is no longer incomplete):
<blockquote class="std">
The declaration of a static data member in its class definition is not a definition and may be of an incomplete
type<del> other than cv-qualified void</del>.&hellip;
</blockquote></p>

<p>Change in §13.6 [over.built] paragraph 15 (regarding comparison operator declarations):
<blockquote class="std">
For every T, where T is an enumeration type<ins>, void</ins> or a pointer type, there exist candidate operator functions of
the form
<pre>
	bool operator&lt;(T , T );
	bool operator&gt;(T , T );
	bool operator&lt;=(T , T );
	bool operator&gt;=(T , T );
	bool operator==(T , T );
	bool operator!=(T , T );
</pre>
</blockquote></p>

<p>Change in §14.1 [temp.param] paragraph 7:
<blockquote class="std">
A non-type template-parameter shall not be declared to have floating point<del>,</del> <ins>or</ins> class<del>, or void</del> type.&hellip;
</blockquote></p>

<p>Change in §14.8.2 [temp.deduct] paragraph 8.2 (details regarding when type deduction can fail):
<blockquote class="std">
— Attempting to create an array with an element type that is <del>void,</del> a function type, a reference type, or
an abstract class type, or attempting to create an array with a size that is zero or negative.&hellip;
</blockquote></p>

<p>Remove §14.8.2 [temp.deduct] paragraph 8.6 (details regarding when type deduction can fail):
<blockquote class="stddel">
— Attempting to create a reference to void
</blockquote></p>

<p>Change in §14.8.2 [temp.deduct] paragraph 8.10 (details regarding when type deduction can fail):
<blockquote class="std">
— Attempting to create a function type in which <del>a parameter has a type of void, or in which</del> the return
type is a function type or array type.
</blockquote></p>

<p>Change in §15.1 [except.throw] paragraph 3 (void is no longer incomplete):
<blockquote class="std">
Throwing an exception copy-initializes (8.5, 12.8) a temporary object, called the <i>exception object</i>. The
temporary is an lvalue and is used to initialize the variable declared in the matching <i>handler</i> (15.3). If the
type of the exception object would be an incomplete type or a pointer to an incomplete type <del>other than
(possibly cv-qualified) void</del> the program is ill-formed.
</blockquote></p>

<p>Change in §15.3 [except.handle] paragraph 1 (void is no longer incomplete):
<blockquote class="std">
&hellip;
The <i>exception-declaration</i> in a <i>handler</i> describes the type(s) of exceptions that can cause that <i>handler</i> to
be entered. The <i>exception-declaration</i> shall not denote an incomplete type, an abstract class type, or an
rvalue reference type. The <i>exception-declaration</i> shall not denote a pointer or reference to an incomplete
type<del>, other than void*, const void*, volatile void*, or const volatile void*</del>.
</blockquote></p>

<p>Change in §15.4 [except.handle] paragraph 2 (void is no longer incomplete):
<blockquote class="std">
A type denoted in a <i>dynamic-exception-specification</i> shall not denote an incomplete type or an rvalue reference
type. A type denoted in a <i>dynamic-exception-specification</i> shall not denote a pointer or reference to
an incomplete type<del>, other than “pointer to cv void”.</del> A type cv T, “array of T”, or “function returning T”
denoted in a dynamic-exception-specification is adjusted to type T, “pointer to T”, or “pointer to function
returning T”, respectively. A dynamic-exception-specification denotes an exception specification that is the
set of adjusted types specified thereby.
</blockquote></p>

<p>Change in §20.10.4.3 Type properties [meta.unary.prop]:<br />
<b>Remove explicit mentions of <code>void</code> other than in <code>is_void</code></b> <i>(complicated to list, spanning across multiple tables).</i>
</p>

<h2><a id="Acknowledgments">Acknowledgments</a></h2>
<p>Though a change to the langauge such as this has been discussed informally by several in the past, particularly by Sean Parent, the direct motivation for this proposal was a discussion<sup><a href="#References_AVoV">3</a></sup> in the std-proposals group (a thread that the author of this proposal did not start). Many suggestions and alternatives mentioned in this proposal come from those who took part in that discussion.</p>
<p>In addition to those mentioned above, Richard Smith provided support and early feedback during the writing of this proposal. I also hijacked his formatting for use in this document.</p>

<h2><a id="References">References</a></h2>
<p>[<a id="References_FoGP">1</a>] James C. Dehnert and Alexander Stepanov: "Fundamentals of Generic Programming" <a href="http://www.stepanovpapers.com/DeSt98.pdf">http://www.stepanovpapers.com/DeSt98.pdf</a></p>
<p>[<a id="References_Expected">2</a>] Vicente J. Botet Escriba and Pierre Talbot: "A proposal to add a utility class to represent expected monad" <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4109.pdf">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4109.pdf</a></p>
<p>[<a id="References_AVoV">3</a>] <i>Various Participants</i> "Allow values of void" Discussion <a href="https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/05prNzycvYU">https://groups.google.com/a/isocpp.org/forum/#!topic/std-proposals/05prNzycvYU</a></p>
</body>
</html>
