dimanche 21 novembre 2021

Resolution of class template with different primary template's default argument and partial specialization's specializing argument

I have two class (struct) templates A and B, which are identical except that the template specializing second argument (in their partial specializations) and the default second argument (in their primary templates) are the same (void and void respectively) in A, while different (int and void respectively) in B.

#include <bits/stdc++.h>

/* primary class template A */
template <int N, class = void>
struct A : std::false_type {};

/* partial specialization of A */
template <int N>
struct A<N, std::enable_if_t<(N != 0), void>> : std::true_type {};

/* primary class template B */
template <int N, class = void>
struct B : std::false_type {};

/* partial specialization of B */
template <int N>
struct B<N, std::enable_if_t<(N != 0), int>> : std::true_type {};

int main() {

    std::cout << A<0>::value << std::endl; // 0 (i.e. A<0> extends std::false_type)
    std::cout << A<1>::value << std::endl; // 1 (i.e. A<1> extends std::true_type)

    std::cout << B<0>::value << std::endl; // 0 (i.e. B<0> extends std::false_type)
    std::cout << B<1>::value << std::endl; // 0 (i.e. B<1> extends std::false_type)

    return 0;
}

As is apparent from the output, B<1> resolves to the primary template whereas A<1> resolves to the partial specialization (apparently due to the aforementioned difference). This is rather counterintuitive as I expected the exact opposite to happen. But why does it happen like this? How does the compiler decide which version to resolve?

Aucun commentaire:

Enregistrer un commentaire