This is the code I am working with:
#include <iostream>
#include <type_traits>
using namespace std;
using match_type = void;
using match_type_bad = int;
// version A
template <typename T, typename Attempt = match_type>
struct simple_check : false_type {};
// version B
template <typename T>
struct simple_check<T, T> : true_type {};
int main() {
cout << simple_check<match_type>::value << endl;
cout << simple_check<match_type_bad>::value << endl;
}
The program with this template specialization ends up having the output as:
1
0
There is a confusion in my understanding of C++'s tmp as I was assuming that the output should have been 1 1
.
My reasoning was:
With simple_check<match_type>
it goes into version B and then gets expanded to simple_check<match_type, match_type>
which inherits from true_type
. So 1
as expected.
Shouldn't the same apply to simple_check<match_type_bad>
?
With this logic, any type X
into simple_check<X>
should always be version B.
It seems that version A's default value of match_type
is enforcing some rule when it decides on version B.
Why is version A affecting version B? Possibly something else?
When you instatiate a template it always uses the base version before looking at the specializations. It works here since the second template parameter has a default value of match_type
.
So
simple_check<match_type> => simple_check<match_type, match_type>
^^ this uses the default value
simple_check<match_type_bad> => simple_check<match_type_bad, match_type>
^^ again, default value
After this is done, the compiler looks at the specializations.
The specialization only works if the template parameters are the same, so for the first check the specialization will be chosen over the base template, and for the second the base template will be used since the specialization is not valid.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With