mercredi 30 novembre 2016

Class template specialization oddity

While trying to implement a few things relying on variadic templates, I stumbled accross something I cannot explain. I boiled down the problem to the following code snippet:

template <typename ... Args>
struct A {};

template <template <typename...> class Z, typename T>
struct test;

template <template <typename...> class Z, typename T>
struct test<Z, Z<T>> {
    static void foo() {
        std::cout << "I'm more specialized than the variadic spec, hehe!" << std::endl;
    }
};

template <template <typename...> class Z, typename T, typename ... Args>
struct test<Z, Z<T, Args...>> {
    static void foo() {
        std::cout << "I'm variadic!" << std::endl;
    }
};

int main() {
    test<A, A<int>>::foo();
}

Under gcc, it produces an error because it considers both specializations to be equally specialized when trying to instantiate test<A, A<int>>:

main.cpp: In function 'int main()':

main.cpp:25:24: error: ambiguous template instantiation for 'struct test<A, A<int> >'

         test<A, A<int>>::foo();

                        ^~

main.cpp:11:12: note: candidates are: template<template<class ...> class Z, class T> struct test<Z, Z<T> > [with Z = A; T = int]

     struct test<Z, Z<T>> {

            ^~~~~~~~~~~~~

main.cpp:18:12: note:                 template<template<class ...> class Z, class T, class ... Args> struct test<Z, Z<T, Args ...> > [with Z = A; T = int; Args = {}]

     struct test<Z, Z<T, Args...>> {

However, clang deems the first specialization "more specialized" (through partial ordering?) as it compiles fine and prints:

I'm more specialized than the variadic spec, hehe!

A live demo can be found on Coliru. I also tried using gcc's HEAD version and got the same errors.

My question here is: since these two well-known compilers behave differently, which one is right and is this piece of code correct C++?

Aucun commentaire:

Enregistrer un commentaire