Class template specialization priority/ambiguity

前端 未结 1 803
南旧
南旧 2021-02-07 07:23

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:

相关标签:
1条回答
  • 2021-02-07 08:04

    From temp.class.order:

    For two class template partial specializations, the first is more specialized than the second if, given the following rewrite to two function templates, the first function template is more specialized than the second according to the ordering rules for function templates ([temp.func.order]):

    • Each of the two function templates has the same template parameters as the corresponding partial specialization.

    • Each function template has a single function parameter whose type is a class template specialization where the template arguments are the corresponding template parameters from the function template for each template argument in the template-argument-list of the simple-template-id of the partial specialization.

    The order of:

    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;
        }
    };
    

    depends on the order of:

    template <template <typename...> class Z, typename T>
    void bar(test<Z, Z<T>>); // #1
    template <template <typename...> class Z, typename T, typename ... Args>
    void bar(test<Z, Z<T, Args...>>); // #2
    

    From [temp.func.order]:

    Partial ordering selects which of two function templates is more specialized than the other by transforming each template in turn (see next paragraph) and performing template argument deduction using the function type. The deduction process determines whether one of the templates is more specialized than the other. If so, the more specialized template is the one chosen by the partial ordering process.

    To produce the transformed template, for each type, non-type, or template template parameter (including template parameter packs ([temp.variadic]) thereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template.

    Using the transformed function template's function type, perform type deduction against the other template as described in [temp.deduct.partial].

    By those paragraph, for any function transformed from any synthesized template Z0 and type T0, which can form #1, we can do type deduction with #2. But functions transformed from #2 with fictitious template Z2 with any type T2 and any non-empty set of Args2 can't be deduced from #1. #1 is obviously more specialized than #2.

    clang++ is right in this case.


    Actually, this one and this one are failed to compile (because of ambiguous) in both g++ and clang. It seems like both compilers have hard time with template template parameters. (The latter one is clearly ordered because its order is the same of no function call).

    0 讨论(0)
提交回复
热议问题