<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; }
keyword { color:#800000; font-weight:bold; }
consistent { font-weight: bold; color: #005100; }
inconsistent { font-weight: bold; color: #CC0000; }
meh { font-weight: bold; color: #FFAA00; }

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, th, td { border: 1px solid black; }

th, td { vertical-align: top; }

/*]]>*/
</style>

<title>Access Checking on Specializations</title>
</head>
<body>

<p style="text-align: right; float: right">
ISO/IEC JTC1 SC22 WG21<br>
Document Number: P0692R1<br>
Matt Calabrese (<a href="mailto:metaprogrammingtheworld@gmail.com">metaprogrammingtheworld@gmail.com</a>)<br>
2017-11-10<br>
</p>

<h1>Access Checking on Specializations</h1>

<h2><a id="Abstract">Abstract</a></h2>
<p>This paper attempts to address a long-standing hole in the ability for developers to specialize templates on their <code>private</code> and <code>protected</code> nested class-types. It also identifies an implementation divergence between compilers.</p>

<h3><a id="AbstractExample">Abstract Code Example</a></h3>
<p>To be clear about what is being discussed, the following code is a minimal example:</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:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> trait<span style='color:#800080; '>;</span>

<span style='color:#800000; font-weight:bold; '>class</span> class_ <span style='color:#800080; '>{</span>
  <span style='color:#800000; font-weight:bold; '>class</span> impl<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#696969; '>// Not allowed in standard C++ (impl is private)</span>
<span style='color:#800000; font-weight:bold; '>template</span><span style='color:#800080; '>&lt;</span><span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> trait<span style='color:#800080; '>&lt;</span>class_<span style='color:#800080; '>::</span>impl<span style='color:#800080; '>></span><span style='color:#800080; '>;</span>
</pre>

<p>It is important to note that even though the above specialization of <code>trait</code> is not allowed according to the standard, it <b>builds with all compilers that were tested</b>, including various versions of gcc, clang, icc, and msvc. Already, for the sake of standardizing existing practice, one might argue that this should be allowed. Though this specific code seems to have consistent acceptance between implementations, similar code that deals with <i>partial</i> (as opposed to explicit) specializations is permitted in some compilers while disallowed in others. This paper presents rationale for why code such as this is desirable along with options for how to adjust the language pending the committee's agreement that specializations such as this should be sanctioned.</p>

<h2><a id="History">Revision History</a></h2>
<p>Revision 1
<ul>
<li>Added wording after acceptance of "Option A" by EWG in Albuquerque, November 2017.</li>
<li>Added Jens Maurer to the Acknowledgments section for consultation during wording specification.</li>
</ul>
</p>

<h2><a id="Motivation">Motivating Case</a></h2>
<p>From the minimal code above, it may not be clear why anyone may desire this functionality, but it does come up in practice and is how the differences in compiler behavior were discovered. For example, in development of a standard library proposal<sup><a href="#References_call0">[1]</a></sup><sup><a href="#References_call1">[2]</a></sup>, I frequently encountered the desire to specialize namespace-scope traits on a <code>private</code> nested type of a <code>struct</code>. This is due to function objects of the library frequently returning an instance of an <i>unspecified</i> type that needs to model a specific concept with associated traits. If this sounds rather abstract, consider the more familiar case of a <code>Range</code> type that may have a <code>private</code> iterator type. Because this nested type is <code>private</code>, it is not possible to specialize <code>iterator_traits</code> on it directly.</p>

<h3><a id="Divergence">Implementation Divergence</a></h3>

<p>While all tested compilers allow the non-standard specialization seen in this paper's abstract, something similar but with a partial specialization uncovers implementation divergence. Consider the following:</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:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> trait<span style='color:#800080; '>;</span>

<span style='color:#800000; font-weight:bold; '>class</span> class_ <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> U<span style='color:#800080; '>></span>
  <span style='color:#800000; font-weight:bold; '>struct</span> impl<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#696969; '>// Not allowed in standard C++ (impl is private)</span>
<span style='color:#696969; '>// Not allowed in clang, icc</span>
<span style='color:#696969; '>// Allowed in gcc, msvc</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> U<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> trait<span style='color:#800080; '>&lt;</span>class_<span style='color:#800080; '>::</span>impl<span style='color:#800080; '>&lt;</span>U<span style='color:#800080; '>></span><span style='color:#800080; '>></span><span style='color:#800080; '>;</span>
</pre>

<h3>Workarounds</h3>

<p>A developer who is not a language lawyer may incorrectly believe that there is an obvious, standard solution to this problem: declare the trait to be a <code>friend</code> of <code>class_</code>. Of course, this will not actually work because declaring a specialization of a trait to be a <code>friend</code> does not mean that the declarator's <i>template argument list</i> can refer to <code>private</code> members of the class. All that such a <code>friend</code> declaration means is that the <i>definition</i> of the trait would have access. In existing C++, if the trait, itself, were nested in a hypothetical type <code>foo</code>, then <code>foo</code> could be befriended and we'd be able to directly specialize the trait. Because the trait is at namespace scope, this is not an option.</p>

<p>An actual workaround is to either make <code>impl</code> <code>public</code>, or make an alias of it <code>public</code>, or put an alias or <code>impl</code> itself in a hidden details namespace. All of these options may be considered suboptimal by some developers as they require directly exposing a type that is [arguably] most-naturally a <code>private</code> nested type.</p>

<h2><a id="Related">Related Issues</a></h2>
<p>James Dennett discovered a related issue<sup><a href="#References_issue_182">[3]</a></sup> submitted by John Spicer in 1999 that attempts to address part of the problem (though only for <i>explicit</i> specializations). Resolution of this issue in 2002 was to consider this lack of ability to declare a specialization to be NAD, however there is still no direct way to accomplish what is desired. As well, as was described earlier, the resolution from the issue was never actually implemented in gcc, clang, icc, or msvc, so there may be reason to reconsider that resolution.</p>

<h2><a id="PR">Proposal</a></h2>
<p>Assuming that the committee feels this is a problem worth solving, this paper presents four possible solutions to consider, with a preference for one of the alternatives. A table comparing user code corresponding to each option is presented after their enumeration.</p>

<h3><a id="OptionA">Option A</a></h3>
<p>The first option is to standardize a generalization of existing practice and simply allow an explicit or partial specialization to ignore access when the <code>template</code> being refered to is not dependent on a <code>template</code> parameter. Very important to note is that this does not grant the <i>definition</i> of the template any privileged access that it wouldn't already have had. Because it would not affect access when the <code>template</code> itself is <i>dependent</i>, it would not change the behavior of existing, well-formed code (specifically, it would not break specializations that rely on access playing a role in SFINAE in a partial specialization, which is a common pattern when creating traits).</p>

<p>"Option A" is somewhat consistent with existing explicit instantiation rules and also with the behavior of explicit specializations as it exists in all of the tested compilers, however this does contradict the resolution of issue 182<sup><a href="#References_issue_182">[3]</a></sup>.</p>

<h3><a id="OptionB">Option B</a></h3>
<p>The second option is to make it such that if a <code>class</code> <code>class_</code> with a <code>private</code> nested type <code>impl</code> declares a specialization <code>trait&lt;class_::impl&gt;</code> to be a <code>friend</code>, then that specialization can be declared and defined outside of the <code>class</code>.</p>

<p>One drawback of "Option B" is that it gives the <i>definition</i> of the trait privileged access to <code>class_</code> when it otherwise may not be necessary, though subjectively, this is a minor drawback.</p>

<h3><a id="OptionC">Option C</a></h3>
<p>The third option is very similar to the second, except the <code>friend</code> declaration appears in the nested class itself as opposed to the type(s) that it is nested in. This has some similar drawbacks and is also strange in that the specialization does not need privileged access of the <i>nested</i> <code>class</code> for the declaration to be valid, but rather, it needs privileged access to the type that <i>contains</i> it. This option is included because an informal poll of a very small set of C++ programmers did favor it.</p>

<h3><a id="OptionD">Option D</a></h3>
<p>The final option is to allow a <code>template</code> (as opposed to a <i>specialization</i> of a <code>template</code>) to be specified as a <code>friend</code>. This would be a new kind of <code>friend</code> declaration and would be provided by specifying <i>only</i> the <code>template</code> name in the <code>friend</code> declaration rather than a specialization of that <code>template</code>. This would not give the <i>definition</i> of the trait any privileged access at all, which may be considered a positive aspect of this choice. Of course, privileged access can still be granted via a normal <code>friend</code> declaration if it is actually desired.</p>

<h3><a id="OptionComparison">Comparison of Options</a></h3>

<p>Below is a side-by-side comparison of all of the options described above.</p>

<table>

<tr>
<th>Option A</th>
<th>Option B</th>
<th>Option C</th>
<th>Option D</th>
</tr>
<tr>
<td>
<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:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> trait<span style='color:#800080; '>;</span>

<span style='color:#800000; font-weight:bold; '>class</span> class_ <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> U<span style='color:#800080; '>></span>
  <span style='color:#800000; font-weight:bold; '>struct</span> impl<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#696969; '>// This would just work. </span>
<span style='color:#696969; '>// Tested compilers already allow
// explicit specializations.</span>
<span style='color:#696969; '>// gcc and msvc already allow
// partial specializations.</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> U<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> trait<span style='color:#800080; '>&lt;</span>class_<span style='color:#800080; '>::</span>impl<span style='color:#808030; '>&lt;</span>U<span style='color:#808030; '>></span><span style='color:#800080; '>></span><span style='color:#800080; '>;</span>
</pre>
</td>
<td>
<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:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> trait<span style='color:#800080; '>;</span>

<span style='color:#800000; font-weight:bold; '>class</span> class_ <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> U<span style='color:#800080; '>></span>
  <span style='color:#800000; font-weight:bold; '>struct</span> impl<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> U<span style='color:#800080; '>></span>
  <span style='color:#800000; font-weight:bold; '>friend</span> <span style='color:#800000; font-weight:bold; '>struct</span> trait<span style='color:#800080; '>&lt;</span>impl<span style='color:#808030; '>&lt;</span>U<span style='color:#808030; '>></span><span style='color:#800080; '>></span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#696969; '>// Works because of the friend declaration.</span>
<span style='color:#696969; '>// Side-effect: definition now also has
// privileged access to class_.</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> U<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> trait<span style='color:#800080; '>&lt;</span>class_<span style='color:#800080; '>::</span>impl<span style='color:#808030; '>&lt;</span>U<span style='color:#808030; '>></span><span style='color:#800080; '>></span><span style='color:#800080; '>;</span>
</pre>
</td>
<td>
<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:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> trait<span style='color:#800080; '>;</span>

<span style='color:#800000; font-weight:bold; '>class</span> class_ <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> U<span style='color:#800080; '>></span>
  <span style='color:#800000; font-weight:bold; '>struct</span> impl <span style='color:#800080; '>{</span>
    <span style='color:#800000; font-weight:bold; '>friend</span> <span style='color:#800000; font-weight:bold; '>struct</span> trait<span style='color:#800080; '>&lt;</span>impl<span style='color:#800080; '>></span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#696969; '>// Works because of the friend declaration.</span>
<span style='color:#696969; '>// Side-effect: definition now also has</span>
<span style='color:#696969; '>// privileged access to class_::impl.</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> U<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> trait<span style='color:#800080; '>&lt;</span>class_<span style='color:#800080; '>::</span>impl<span style='color:#808030; '>&lt;</span>U<span style='color:#808030; '>></span><span style='color:#800080; '>></span><span style='color:#800080; '>;</span>
</pre>
</td>
<td>
<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:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> trait<span style='color:#800080; '>;</span>

<span style='color:#800000; font-weight:bold; '>class</span> class_ <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> U<span style='color:#800080; '>></span>
  <span style='color:#800000; font-weight:bold; '>struct</span> impl<span style='color:#800080; '>;</span>

  <span style='color:#800000; font-weight:bold; '>friend</span> trait<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#696969; '>// Works because of the friend declaration.</span>
<span style='color:#696969; '>// Definition does not get privileged access.</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> U<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> trait<span style='color:#800080; '>&lt;</span>class_<span style='color:#800080; '>::</span>impl<span style='color:#808030; '>&lt;</span>U<span style='color:#808030; '>></span><span style='color:#800080; '>></span><span style='color:#800080; '>;</span>
</pre>
</td>
</tr>
</table>

<h3><a id="Prefered">Prefered Solution</a></h3>
<p>The author of this paper is most in favor of "Option A". Behavior like this has existed in commonly-used compilers without problem for at least 15 years and it doesn't require adding a new kind of feature to the language that only experts would know about. It is also somewhat of a safer choice compared to the alternatives as it does not require altering specialization behavior or access in novel ways that have yet to be explored.</p>

<h3><a id="Wording">Wording</a></h3>
<p>Wording for "Option A":</p>
<p><i>Note: This wording is relative to N4700 (Pre-Albuquerque, 2017-10-16).</i></p>

<p>Add a paragraph to <b>§17.6.5 Class template partial specializations [temp.class.spec]</b> after paragraph 9:</p>

<blockquote class="std">
<ins>The usual access checking rules do not apply to non-dependent names used to specify template arguments of the <i>simple-template-id</i> of the partial specialization. [<i>Note:</i> The template
arguments may be private types or objects that would normally not be accessible. Dependent names cannot be checked when declaring the partial specialization, but will be checked when substituting into the partial specialization. <i>— end note</i>]</ins>
</blockquote>

<p>Add a paragraph to <b>§17.8 Template instantiation and specialization [temp.spec]</b> after paragraph 5:</p>

<blockquote class="std">
<ins>The usual access checking rules do not apply to names in a declaration of an explicit instantiation or explicit
specialization, with the exception of names appearing in a function body, default argument, <i>base-clause</i>, <i>member-specification</i>, <i>enumerator-list</i>, or static data member or variable template initializer. [<i>Note:</i> In particular, the template
arguments and names used in the function declarator (including parameter types, return types and exception
specifications) may be private types or objects that would normally not be accessible. <i>— end note</i>]</ins>
</blockquote>

<p>Remove <b>§17.8.2 Explicit instantiation [temp.explicit]</b> paragraph 14:</p>

<blockquote class="std">
<del>The usual access checking rules do not apply to names used to specify explicit instantiations. [<i>Note:</i> In
particular, the template arguments and names used in the function declarator (including parameter types,
return types and exception specifications) may be private types or objects which would normally not be
accessible and the template may be a member template or member function which would not normally be
accessible. <i>— end note</i>]</del>
</blockquote>

<h2><a id="Acknowledgments">Acknowledgments</a></h2>
<p>Thanks to James Dennett and Richard Smith for their interest and research. Also thanks to Jens Maurer for help with wording.</p>

<h2><a id="References">References</a></h2>
<p>[<a id="References_call0">1</a>] Matt Calabrese: "A Single Generalization of std::invoke, std::apply, and std::visit" P0376R0 <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0376r0.html" target="_blank">http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0376r0.html</a></p>
<p>[<a id="References_call1">2</a>] Matt Calabrese: "Call: A Library that Will Change the Way You Think about Function Invocations" <a href="https://www.youtube.com/watch?v=Fjw7NjndQ50&list=PLTXJhw4sOAviW1OdRgPlxU5m5GU2UzJiJ" target="_blank">https://www.youtube.com/watch?v=Fjw7NjndQ50&list=PLTXJhw4sOAviW1OdRgPlxU5m5GU2UzJiJ</a></p>
<p>[<a id="References_issue_182">3</a>] C++ Standard Core Language Issue 182. "Access checking on explicit specializations" <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#182" target="_blank">http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html</a></p>

</body></html>
