<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2037: atomic free functions incorrectly specified</title>
<meta property="og:title" content="Issue 2037: atomic free functions incorrectly specified">
<meta property="og:description" content="C++ library issue. Status: Resolved">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2037.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#Resolved">Resolved</a> status.</em></p>
<h3 id="2037"><a href="lwg-defects.html#2037">2037</a>. <code>atomic</code> free functions incorrectly specified</h3>
<p><b>Section:</b> 32.5.2 <a href="https://wg21.link/atomics.syn">[atomics.syn]</a> <b>Status:</b> <a href="lwg-active.html#Resolved">Resolved</a>
 <b>Submitter:</b> Pete Becker <b>Opened:</b> 2011-03-01 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="lwg-index-open.html#atomics.syn">active issues</a> in [atomics.syn].</p>
<p><b>View all other</b> <a href="lwg-index.html#atomics.syn">issues</a> in [atomics.syn].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Resolved">Resolved</a> status.</p>
<p><b>Discussion:</b></p>
<p>In earlier specifications of atomics the template specialization <code>atomic&lt;<i>integer</i>&gt;</code> 
was derived from <code>atomic_integer</code> (e.g. <code>atomic&lt;int&gt;</code> was derived from <code>atomic_int</code>), 
and the working draft required free functions such as</p>

<blockquote><pre>
int atomic_load(const atomic_int*)
</pre></blockquote>

<p>for each of the <code>atomic_integer</code> types. This worked fine with normal function overloading.</p>

<p>For the post-Batavia working draft, N3193 removed the requirement that <code>atomic&lt;integer&gt;</code> 
be derived from <code>atomic_integer</code> and replaced the free functions taking pointers to 
<code>atomic_integer</code> with template functions taking <code>atomic_type*</code>, such as</p>

<blockquote><pre>
template &lt;class T&gt; T atomic_load(const atomic_type*);
</pre></blockquote>

<p>and a code comment explaining that <code>atomic_type</code> can be either <code>atomic&lt;T&gt;</code> or a 
named base class of <code>atomic&lt;T&gt;</code>. The latter possibility is supposed to allow existing 
implementations based on the previous specification to continue to conform.</p>

<p>From history, this allowance seems to imply that functions like <code>atomic_load</code> can be non-template 
free functions, as they were before. The explicit requirements do not allow this, and, by requiring that 
they be templates, make them far more complicated. As the specification is currently written, code that 
uses an implementation that uses a base class would have to provide an explicit template type:</p>

<blockquote><pre>
atomic&lt;int&gt; my_atomic_int;
atomic_load&lt;int&gt;(&amp;my_atomic_int);
</pre></blockquote>

<p>That type argument isn't needed when <code>atomic_type</code> is <code>atomic&lt;T&gt;</code>, but cautious 
users would always provide it to make their code portable across different implementations of the 
standard library.</p>

<p>One possibility for the implementor would be to do some template meta-programming to infer the type 
<code>T</code> when there are no function parameters of type <code>T</code>, but without running afoul of the 
prohibition on adding parameters with default values (16.4.6.4 <a href="https://wg21.link/global.functions">[global.functions]</a>/3).</p>

<p>So the promise that implementations of the previous specification continue to conform has not been 
met. The specification of these free functions should be rewritten to support library code written to 
the previous specification or the vacuous promise should be removed.
</p>

<p><i>[2011-03-08: Lawrence comments and drafts wording:]</i></p>


<p>One of the goals is to permit atomics code to compile under both C and C++. Adding explicit 
template arguments would defeat that goal.
<p/>
The intent was to permit the normal function overloads for <code>atomic_int</code> when <code>atomic_int</code> 
is distinct from <code>atomic&lt;int&gt;</code>. That intent was not reflected in the wording.
</p>

<blockquote class="note">
<p>Proposed Resolution</p>
<p>Explicitly permit free functions.</p>

<ol>
<li>
<p>Edit within the header <code>&lt;atomic&gt;</code> synopsis 32.5.2 <a href="https://wg21.link/atomics.syn">[atomics.syn]</a> as follows:</p>

<blockquote><pre>
<i>// 29.6.1, general operations on atomic types</i>
<del><i>// In the following declarations, <em>atomic_type</em> is either</i>
<i>// </i><code>atomic&lt;T&gt;</code><i> or a named base class for</i> <code>T</code><i> from</i>
<i>// Table 145 or inferred from</i>
<i>// Table 146.</i></del>
<ins><i>// In the following declarations, <em>atomic-type</em> is either</i> 
<i>// </i><code>atomic&lt;T&gt;</code><i> or a named base class for</i> <code>T</code><i> from</i>
<i>// Table 145 or inferred from</i>
<i>// Table 146.</i>
<i>// If it is </i><code>atomic&lt;T&gt;</code><i>, then the declaration is a template
// declaration prefixed with</i> <code>template &lt;class T&gt;</code></ins>
<del>template &lt;class T&gt;</del>
bool atomic_is_lock_free(const volatile <em><del>atomic_type</del><ins>atomic-type</ins></em>*);
<del>template &lt;class T&gt;</del>
bool atomic_is_lock_free(const <em><del>atomic_type</del><ins>atomic-type</ins></em>*);
<del>template &lt;class T&gt;</del>
void atomic_init(volatile <em><del>atomic_type</del><ins>atomic-type</ins></em>*, T);
<del>template &lt;class T&gt;</del>
void atomic_init(<em><del>atomic_type</del><ins>atomic-type</ins></em>*, T);
<del>template &lt;class T&gt;</del>
void atomic_store(volatile <em><del>atomic_type</del><ins>atomic-type</ins></em>*, T);
<del>template &lt;class T&gt;</del>
void atomic_store(<em><del>atomic_type</del><ins>atomic-type</ins></em>*, T);
<del>template &lt;class T&gt;</del>
void atomic_store_explicit(volatile <em><del>atomic_type</del><ins>atomic-type</ins></em>*, T, memory_order);
<del>template &lt;class T&gt;</del>
void atomic_store_explicit(<em><del>atomic_type</del><ins>atomic-type</ins></em>*, T, memory_order);
<del>template &lt;class T&gt;</del>
T atomic_load(const volatile <em><del>atomic_type</del><ins>atomic-type</ins></em>*);
<del>template &lt;class T&gt;</del>
T atomic_load(const <em><del>atomic_type</del><ins>atomic-type</ins></em>*);
<del>template &lt;class T&gt;</del>
T atomic_load_explicit(const volatile <em><del>atomic_type</del><ins>atomic-type</ins></em>*, memory_order);
<del>template &lt;class T&gt;</del>
T atomic_load_explicit(const <em><del>atomic_type</del><ins>atomic-type</ins></em>*, memory_order);
<del>template &lt;class T&gt;</del>
T atomic_exchange(volatile <em><del>atomic_type</del><ins>atomic-type</ins></em>*, T);
<del>template &lt;class T&gt;</del>
T atomic_exchange(<em><del>atomic_type</del><ins>atomic-type</ins></em>*, T);
<del>template &lt;class T&gt;</del>
T atomic_exchange_explicit(volatile <em><del>atomic_type</del><ins>atomic-type</ins></em>*, T, memory_order);
<del>template &lt;class T&gt;</del>
T atomic_exchange_explicit(<em><del>atomic_type</del><ins>atomic-type</ins></em>*, T, memory_order);
<del>template &lt;class T&gt;</del>
bool atomic_compare_exchange_weak(volatile <em><del>atomic_type</del><ins>atomic-type</ins></em>*, T*, T);
<del>template &lt;class T&gt;</del>
bool atomic_compare_exchange_weak(<em><del>atomic_type</del><ins>atomic-type</ins></em>*, T*, T);
<del>template &lt;class T&gt;</del>
bool atomic_compare_exchange_strong(volatile <em><del>atomic_type</del><ins>atomic-type</ins></em>*, T*, T);
<del>template &lt;class T&gt;</del>
bool atomic_compare_exchange_strong(<em><del>atomic_type</del><ins>atomic-type</ins></em>*, T*, T);
<del>template &lt;class T&gt;</del>
bool atomic_compare_exchange_weak_explicit(volatile <em><del>atomic_type</del><ins>atomic-type</ins></em>*, T*, T,
  memory_order, memory_order);
<del>template &lt;class T&gt;</del>
bool atomic_compare_exchange_weak_explicit(<em><del>atomic_type</del><ins>atomic-type</ins></em>*, T*, T.
  memory_order, memory_order);
<del>template &lt;class T&gt;</del>
bool atomic_compare)exchange_strong_explicit(volatile <em><del>atomic_type</del><ins>atomic-type</ins></em>*, T*, T,
  memory_order, memory_order);
<del>template &lt;class T&gt;</del>
bool atomic_compare_exchange_strong_explicit(<em><del>atomic_type</del><ins>atomic-type</ins></em>*, T*, T,
  memory_order, memory_order);
  
<i>// 29.6.2, templated operations on atomic types</i>
<del><i>// In the following declarations, <em>atomic_type</em> is either
// </i><code>atomic&lt;T&gt;</code><i> or a named base class for</i> <code>T</code><i> from
// Table 145 or inferred from
// Table 146.</i></del>
template &lt;class T&gt;
T atomic_fetch_add(volatile <del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T);
template &lt;class T&gt;
T atomic_fetch_add(<del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T);
template &lt;class T&gt;
T atomic_fetch_add_explicit(volatile <del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T, memory_order);
template &lt;class T&gt;
T atomic_fetch_add_explicit(<del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T, memory_order);
template &lt;class T&gt;
T atomic_fetch_sub(volatile <del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T);
template &lt;class T&gt;
T atomic_fetch_sub(<del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T);
template &lt;class T&gt;
T atomic_fetch_sub_explicit(volatile <del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T, memory_order);
template &lt;class T&gt;
T atomic_fetch_sub_explicit(<del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T, memory_order);
template &lt;class T&gt;
T atomic_fetch_and(volatile <del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T);
template &lt;class T&gt;
T atomic_fetch_and(<del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T);
template &lt;class T&gt;
T atomic_fetch_and_explicit(volatile <del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T, memory_order);
template &lt;class T&gt;
T atomic_fetch_and_explicit(<del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T, memory_order);
template &lt;class T&gt;
T atomic_fetch_or(volatile <del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T);
template &lt;class T&gt;
T atomic_fetch_or(<del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T);
template &lt;class T&gt;
T atomic_fetch_or_explicit(volatile <del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T, memory_order);
template &lt;class T&gt;
T atomic_fetch_or_explicit(<del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T, memory_order);
template &lt;class T&gt;
T atomic_fetch_xor(volatile <del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T);
template &lt;class T&gt;
T atomic_fetch_xor(<del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T);
template &lt;class T&gt;
T atomic_fetch_xor_explicit(volatile <del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T, memory_order);
template &lt;class T&gt;
T atomic_fetch_xor_explicit(<del><em>atomic-type</em></del><ins>atomic&lt;T&gt;</ins>*, T, memory_order);

<i>// 29.6.3, arithmetic operations on atomic types</i>
<ins><i>// In the following declarations, <em>atomic-integral</em> is either 
// </i><code>atomic&lt;T&gt;</code> <i>or a named base class for</i> <code>T</code> <i>from 
// Table 145 or inferred from 
// Table 146.
// If it is</i> <code>atomic&lt;T&gt;</code><i>,
// then the declaration is a template specialization declaration prefixed with
//</i> <code>template &lt;&gt;</code></ins>
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_add(volatile <em>atomic-integral</em>*, <em>integral</em>);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_add(<em>atomic-integral</em>*, <em>integral</em>);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_add_explicit(volatile <em>atomic-integral</em>*, <em>integral</em>, memory_order);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_add_explicit(<em>atomic-integral</em>*, <em>integral</em>, memory_order);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_sub(volatile <em>atomic-integral</em>*, <em>integral</em>);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_sub(<em>atomic-integral</em>*, <em>integral</em>);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_sub_explicit(volatile <em>atomic-integral</em>*, <em>integral</em>, memory_order);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_sub_explicit(<em>atomic-integral</em>*, <em>integral</em>, memory_order);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_and(volatile <em>atomic-integral</em>*, <em>integral</em>);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_and(<em>atomic-integral</em>*, <em>integral</em>);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_and_explicit(volatile <em>atomic-integral</em>*, <em>integral</em>, memory_order);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_and_explicit(<em>atomic-integral</em>*, <em>integral</em>, memory_order);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_or(volatile <em>atomic-integral</em>*, <em>integral</em>);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_or(<em>atomic-integral</em>*, <em>integral</em>);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_or_explicit(<em>atomic-integral</em>*, <em>integral</em>, memory_order);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_or_explicit(<em>atomic-integral</em>*, <em>integral</em>, memory_order);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_xor(volatile <em>atomic-integral</em>*, <em>integral</em>);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_xor(<em>atomic-integral</em>*, <em>integral</em>);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_xor_explicit(volatile <em>atomic-integral</em>*, <em>integral</em>, memory_order);
<del>template &lt;&gt;</del>
<em>integral</em> atomic_fetch_xor_explicit(<em>atomic-integral</em>*, <em>integral</em>, memory_order);
</pre></blockquote>
</li>

<li><p>Edit  [atomics.types.operations.general] paragraph 1+2 as follows:</p>

<blockquote><p>
-1- The implementation shall provide the <ins>functions and</ins> function templates identified as 
&quot;general operations on atomic types&quot; in 32.5.2 <a href="https://wg21.link/atomics.syn">[atomics.syn]</a>.
<p/>
-2- In the declarations of these <ins>functions and function</ins> templates, the name <em>atomic-type</em> 
refers to either <code>atomic&lt;T&gt;</code> or to a named base class for <code>T</code> from Table 145 or 
inferred from Table 146.
</p>
</blockquote>
</li>

<li><p>In  [atomics.types.operations.templ] delete paragraph 2:</p>

<blockquote><p>
-1- The implementation shall declare but not define the function templates identified as 
&quot;templated operations on atomic types&quot; in 32.5.2 <a href="https://wg21.link/atomics.syn">[atomics.syn]</a>.
<p/>
<del>-2- In the declarations of these templates, the name <em>atomic-type</em> refers to either 
<code>atomic&lt;T&gt;</code> or to a named base class for <code>T</code> from Table 145 or 
inferred from Table 146.</del>
</p>
</blockquote>
</li>

<li><p>Edit  [atomics.types.operations.arith] paragraph 1+2 as follows:</p>

<blockquote><p>
-1- The implementation shall provide the <ins>functions and</ins> function template 
specializations identified as &quot;arithmetic operations on atomic types&quot; in 
32.5.2 <a href="https://wg21.link/atomics.syn">[atomics.syn]</a>.
<p/>
-2- In the declarations of these <ins>functions and function</ins> template specialization<ins>s</ins>, 
the name <em>integral</em> refers to an integral type and the name <em>atomic-integral</em> 
refers to either <code>atomic&lt;</code><em>integral</em><code>&gt;</code> or to a named base class for 
<em>integral</em> from Table 145 or inferred from Table 146.
</p>
</blockquote>
</li>

</ol>
</blockquote>


<p id="res-2037"><b>Proposed resolution:</b></p><p>
Resolved 2011-03 Madrid meeting by paper <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3278">N3278</a>
</p>




</body>
</html>
