<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html;charset=US-ASCII">
<title>DR: Matching of template template-arguments excludes compatible templates</title>

<style type="text/css">

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.std del { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC; }
blockquote.std ins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8; }
blockquote.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5em padding-right: 0.5em; }
blockquote.stdins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3;
  padding-left: 0.5em; padding-right: 0.5em; }

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; }

table.frontmatter { border: 0;  margin: 0; }

ul.dash { list-style-type: none; }
ul.dash li:before { content: '\2014'; margin-left: -1em }

span.highlight { background-color: #7FDFFF }

</style>

<script type="text/javascript" src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
</head>

<body>
<h1>DR: Matching of template template-arguments excludes compatible templates</h1>
<table class="frontmatter" border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" width="619">
    <tr>
        <td align="left" valign="top">Document number:</td>
        <td>P0522R0</td>
    </tr>
    <tr>
        <td align="left" valign="top">Date:</td>
        <td>2016-11-11</td>
    </tr>
    <tr>
        <td align="left" valign="top">Project:</td>
        <td>Programming Language C++, Core Working Group</td>
    </tr>
    <!--tr>
        <td align="left" valign="top">Revises:</td>
        <td><a href=""></a></td>
    </tr-->
    <tr>
        <td align="left" valign="top">Reply-to:</td>
        <td>James Touton &lt;<a href="mailto:bekenn@gmail.com">bekenn@gmail.com</a>&gt;<br>
        Hubert Tong &lt;<a href="mailto:hubert.reinterpretcast@gmail.com">hubert.reinterpretcast@gmail.com</a>&gt;</td>
    </tr>
</table>

<h2><a id="TableOfContents">Table of Contents</a></h2>
<ol>
    <li><a href="#TableOfContents">Table of Contents</a></li>
    <li><a href="#Introduction">Introduction</a></li>
    <li><a href="#Overview">Overview</a></li>
    <li><a href="#Wording">Wording</a></li>
    <li><a href="#References">References</a></li>
    <li><a href="#Acknowledgments">Acknowledgments</a></li>
</ol>

<h2><a id="Introduction">Introduction</a></h2>
<p>Template <var>template-parameter</var>s only bind to arguments with matching parameter lists.
Matching is currently defined as an exact match; each template parameter in the argument's parameter list must have the same kind and type as the corresponding parameter in the <var>template-parameter</var>'s parameter list.
(There is an ill-advised exception to this rule when a parameter pack appears in the <var>template-parameter</var>'s parameter list; this paper preserves that special behavior.)
The matching rules exclude many reasonable arguments.
This paper adjusts the matching rules to invoke partial ordering to determine when a template <var>template-argument</var> is a valid match for a <var>template-parameter</var>.</p>

<p>This paper resolves Core issue <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4457.html#150">CWG 150</a>.</p>

<h2><a id="Overview">Overview</a></h2>
<p>This paper allows a template <var>template-parameter</var> to bind to a template argument whenever the template parameter is at least as specialized as the template argument.
This implies that any template argument list that can legitimately be applied to the template <var>template-parameter</var> is also applicable to the argument template.</p>

<p>Example:</p>
<pre class="example">
<code class="prettyprint">template &lt;template &lt;int&gt; class&gt; void FI();
template &lt;template &lt;auto&gt; class&gt; void FA();
template &lt;auto&gt; struct SA { /* ... */ };
template &lt;int&gt; struct SI { /* ... */ };
FI&lt;SA&gt;();  // OK; error before this paper
FA&lt;SI&gt;();  // error

template &lt;template &lt;typename&gt; class&gt; void FD();
template &lt;typename, typename = int&gt; struct SD { /* ... */ };
FD&lt;SD&gt;();  // OK; error before this paper (CWG 150)</code>
</pre>

<h2><a id="Wording">Wording</a></h2>
<p>All modifications are presented relative to N4606.</p>

<p>Modify &sect;14.3.3 [temp.arg.template] paragraph 3:</p>
<blockquote class="std">
<p>A <var>template-argument</var> matches a template <var>template-parameter</var> <code>P</code> when <ins><code>P</code> is at least as specialized as the <var>template-argument</var> <code>A</code>.
If <code>P</code> contains a parameter pack, then <code>A</code> also matches <code>P</code> if </ins>each of <ins><code>A</code>'s</ins><del>the</del> template parameters <del>in the <var>template-parameter-list</var> of the <var>template-argument</var>'s corresponding class template or alias template <code>A</code></del> matches the corresponding template parameter in the <var>template-parameter-list</var> of <code>P</code>.
Two template parameters match if they are of the same kind (type, non-type, template), for non-type <var>template-parameter</var>s, their types are equivalent ([temp.over.link]), and for template <var>template-parameter</var>s, each of their corresponding <var>template-parameter</var>s matches, recursively.
When <code>P</code>'s <var>template-parameter-list</var> contains a template parameter pack ([temp.variadic]), the template parameter pack will match zero or more template parameters or template parameter packs in the <var>template-parameter-list</var> of <code>A</code> with the same type and form as the template parameter pack in <code>P</code> (ignoring whether those template parameters are template parameter packs).</p>
<p>[&nbsp;<i>Example:</i></p>
<pre class="example">
<code>template&lt;class T&gt; class A { /* ... */ };
template&lt;class T, class U = T&gt; class B { /* ... */ };
template<del> </del>&lt;class ... Types&gt; class C { /* ... */ };
<ins>template&lt;auto n&gt; class D { /* ... */ };</ins>
template&lt;template&lt;class&gt; class P&gt; class X { /* ... */ };
template&lt;template&lt;class ...&gt; class Q&gt; class Y { /* ... */ };
<ins>template&lt;template&lt;int&gt; class R&gt; class Z { /* ... */ };</ins>
X&lt;A&gt; xa; // <em>OK</em>
X&lt;B&gt; xb; // <em><ins>OK</ins><del>ill-formed: default arguments for the parameters of a template argument are ignored</del></em>
X&lt;C&gt; xc; // <em><ins>OK</ins><del>ill-formed: a template parameter pack does not match a template parameter</del></em>
Y&lt;A&gt; ya; // <em>OK</em>
Y&lt;B&gt; yb; // <em>OK</em>
Y&lt;C&gt; yc; // <em>OK</em>
<ins>Z&lt;D&gt; zd; // <em>OK</em></ins></code>
</pre>
<p>&mdash;<i>end example</i>&nbsp;]</p>
<p>[&nbsp;<i>Example:</i></p>
<pre class="example">
<code>template &lt;class T&gt; struct eval;
template &lt;template &lt;class, class...&gt; class TT, class T1, class... Rest&gt;
struct eval&lt;TT&lt;T1, Rest...&gt;&gt; { };
template &lt;class T1&gt; struct A;
template &lt;class T1, class T2&gt; struct B;
template &lt;int N&gt; struct C;
template &lt;class T1, int N&gt; struct D;
template &lt;class T1, class T2, int N = 17&gt; struct E;
eval&lt;A&lt;int&gt;&gt; eA; // <em>OK: matches partial specialization of eval</em>
eval&lt;B&lt;int, float&gt;&gt; eB; // <em>OK: matches partial specialization of eval</em>
eval&lt;C&lt;17&gt;&gt; eC; // <em>error: C does not match TT in partial specialization</em>
eval&lt;D&lt;int, 17&gt;&gt; eD; // <em>error: D does not match TT in partial specialization</em>
eval&lt;E&lt;int, float&gt;&gt; eE; // <em>error: E does not match TT in partial specialization</em></code>
</pre>
<p>&mdash;<i>end example</i>&nbsp;]</p>
</blockquote>

<p>Insert a new paragraph after &sect;14.3.3 [temp.arg.template] paragraph 3:</p>
<blockquote class="stdins">
<p>A template <var>template-parameter</var> <code>P</code> is at least as specialized as a template <var>template-argument</var> <code>A</code> if, given the following rewrite to two function templates, the function template corresponding to <code>P</code> is at least as specialized as the function template corresponding to <code>A</code> according to the partial ordering rules for function templates ([temp.func.order]).
Given an invented class template <code>X</code> with the template parameter list of <code>A</code> (including default arguments):</p>
<ul class="dash">
<li>Each of the two function templates has the same template parameters, respectively, as <code>P</code> or <code>A</code>.</li>
<li>Each function template has a single function parameter whose type is a specialization of <code>X</code> with template arguments corresponding to the template parameters from the respective function template where, for each template parameter <code>PP</code> in the template parameter list of the function template, a corresponding template argument <code>AA</code> is formed.
If <code>PP</code> declares a parameter pack, then <code>AA</code> is the pack expansion <code>PP...</code> ([temp.variadic]); otherwise, <code>AA</code> is the <var>id-expression</var> <code>PP</code>.</li>
</ul>
<p>If the rewrite produces an invalid type, then <code>P</code> is not at least as specialized as <code>A</code>.</p>
</blockquote>

<h2><a id="References">References</a></h2>
<ol>
<li>CWG Issue 150: <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4457.html#150">http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4457.html#150</a></li>
</ol>

</body></html>
