Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h2>The surprise</h2> <p>This is a subtle Clang bug, deeply buried in the Standard. The problem is that in almost all cases, non-type template <em>arguments</em> can be converted to the type of the template <em>parameter</em>. E.g. the expression <code>Int&lt;0&gt;</code> has an <code>int</code> literal argument of value <code>0</code> that is being converted to the type <code>unsigned long long</code> of the template parameter <code>N</code>.</p> <p><strong>14.8.2 Template argument deduction [temp.deduct]/2 2nd bullet</strong></p> <blockquote> <p>-- Non-type arguments must match the types of the corresponding non-type template parameters, <strong>or must be convertible to</strong> the types of the corresponding non-type parameters as specified in 14.3.2, otherwise type deduction fails.</p> </blockquote> <p>Since your class template <code>is_int&lt;T&gt;</code> has a partial specialization, we need to look at</p> <p><strong>14.5.5.1 Matching of class template partial specializations [temp.class.spec.match]</strong></p> <blockquote> <p>1 When a class template is used in a context that requires an instantiation of the class, it is necessary to determine whether the instantiation is to be generated using the primary template or one of the partial specializations. <strong>This is done by matching the template arguments of the class template specialization with the template argument lists of the partial specializations</strong>.</p> <p>2 A partial specialization matches a given actual template argument list if the template arguments of the partial specialization <strong>can be deduced from</strong> the actual template argument list (14.8.2).</p> </blockquote> <p>So it would seem that we can proceed to the earlier quote of 14.8.2/2 2nd bullet and match the second specialization (although in that case an even more complicated overload resolution game would have to be played). </p> <h2>The resolution</h2> <p>However, it turns out (as mentioned by @DyP in the comments) that another clause in the Standard supersedes this:</p> <p><strong>14.8.2.5 Deducing template arguments from a type [temp.deduct.type]</strong></p> <blockquote> <p>17 If, in the declaration of a function template with a non-type template-parameter, the non-type templateparameter is used in an expression in the function parameter-list and, if the corresponding template-argument is deduced, <strong>the template-argument type shall match the type of the template-parameter exactly</strong>, except that a template-argument deduced from an array bound may be of any integral type. [ Example:</p> </blockquote> <pre><code>template&lt;int i&gt; class A { / ... / }; template&lt;short s&gt; void f(A&lt;s&gt;); void k1() { A&lt;1&gt; a; f(a); // error: deduction fails for conversion from int to short f&lt;1&gt;(a); // OK } </code></pre> <p>The upshot is that the partial specialization of <code>is_int</code> cannot be deduced because it does not take the exact same type (<code>unsigned long long</code> vs <code>long long</code>) as the <code>Int</code> class template's formal non-type template parameter.</p> <p>You can resolve this by giving the non-type template parameter <code>N</code> in the partial specialization of <code>is_int</code> the same type as the non-type parameter <code>N</code> in the primary template <code>Int</code>.</p> <pre><code>template &lt;IntType N&gt; // ^^^^^^^^ struct is_int&lt;Int&lt;N&gt;&gt; : std::true_type {}; </code></pre> <p><a href="http://coliru.stacked-crooked.com/a/5d0ad7b77db02034"><strong>Live Example</strong></a>.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload