I'm struggling to understand how template specialization for bool works for this slide taken from cppcon 2017
Short question: why (first) primary template handles odd N cases when its signature is
<..., bool = (N % 2 == 0) > ?
Trying to understand myself I simplified down to
#include<iostream>
template<unsigned N, bool =(N%2==0)> struct S { void operator()(){ std::cout << "A\n"; } };
template<unsigned N> struct S<N, true> { void operator()(){ std::cout << "B\n"; } };
int main()
{
S<2>{}();
S<3>{}();
}
which prints B
A
, showings same (yet mysterious to me) behavior as linked talk, but if I change template specialization to
template<unsigned N> struct S<N, false> { void operator()(){ std::cout << "B\n"; } };
-----
it prints A
B
: how compiler chooses between primary S
and its specialization?
The compiler always prefers the specialization over the generalization and thus will always pick it if it can.
The struct S
has a partial template specialization that will only be picked if the second template parameter evaluates to true
, so let's see how that works:
S<2>{}();
Here the template parameter N
is 2 and so 2 % 2 == 0
holds true. Which means the specialization will be picked over the generalized S
because the specialization requires the second parameter to be true
and B
is printed.
This isn't the case for S<3>{}();
because 3 % 2 == 0
holds false, and thus the generalized case is used, giving you A
.
If you swap it around and make the specialization only accept false
for N % 2 == 0
then the results will be the exact opposite, 2 % 2 == 0
still holds true but the specialization only accepts false so it's not picked, 3 % 2 == 0
holds false and thus it will be picked, resulting in AB
.
It's specialization; the compiler choose the most specialized version available.
Ignore for a moment the default value for bool
(that transform S<2>
in S<2, true>
and S<3>
in S<3, false>
); you have
template <unsigned N, bool>
struct S
{ /* something */};
template <unsigned N>
struct S<N, true>
{ /* something */};
The first one is neutral regarding the second (the bool
one) template parameter; so matches both S<2, true>
and S<3, false>
.
The second one require that the second template parameter is true
, so matches only S<2, true>
. And is more specialized than the first one because every match for the second template is also a match for the first one but there are matches for the first one that aren't matches for the second one ( S<3, false>
, by example).
For S<3, false>
the compiler find only a template that matches (the first one) so choose the first one.
For S<2, true>
the compiler find both templates that match and coose (rule of C++) the most specialized, that is the second one.
When you change the true
in false
you have that S<3, false>
matches both version, so the second one is choosed, and S<2, true>
matches only the first one.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.