通常来说,功能模板特化的主要模板是什么是非常直观的,但是,我正在寻找正式的规则来理解更令人惊讶的情况。例如:
template <typename T, typename U>
void f(T, U) {} // (1)
template <typename T>
void f(T, T) {} // (2)
template <>
void f(int, int) {} // (3); specializes (2), not (1); why?
从理论上讲,(3)也可以是(1)的特化,但实验表明并非如此。
最佳答案
让我们集中讨论通用模板(1)和(2)的声明。
这是两个不同的模板,例如(2)不是(1)的特化。好的,现在当我们写一个特化的时候:
template <>
void foo(int, int) {}
当推导要专门化的模板时,编译器将识别出两个候选对象。然后,它必须选择最合适的。这种选择的过程称为"partial ordering of function templates"。选择报价:让我们将S称为匹配模板集。然后,对于S中的每个对(f1,f2),编译器将通过在其类型(resp。non type)参数上应用伪类型(resp。value)来转换f1。然后,它尝试将其与f2匹配。然后,它通过转换f2并尝试将其与f1匹配来执行相同的过程。最后,在经过每一对之后,编译器可以确定哪个模板候选者是最专业的。如果这样做失败,则编译将失败。
在我们的例子中,我们有两个匹配的模板,因此我们应用上述过程:
通过此过程,编译器推断出(2)比(1)更专业,您的特化为(2)。当编译器专注于特定调用时,在重载解析期间将应用相同的过程。
下面是一个说明所有此过程的示例(摘自@Yakk的评论):
template <typename T, typename U>
void f(T, U) { std::cout << "f(1)\n"; } // f(1)
template <typename T>
void f(T, T) { std::cout << "f(2)\n"; } // f(2)
template <>
void f(int, int) { std::cout << "f(3)\n"; } // f(3); specializes f(2), not f(1); why?
// Now the same specialization but without any template overload...
template <typename T, typename U>
void g(T, U) { std::cout << "g(1)\n"; } // g(1)
template <>
void g(int, int) { std::cout << "g(3)\n"; } // g(3); No ambiguity, specializes g(1)
接下来,让我们执行一些调用:f(1, 1); // Prints f(3)
f<int>(1, 1); // Prints f(3)
f<int, int>(1, 1); // Prints f(1)
f(0.1, 0.2); // Prints f(2)
g(1, 1); // Prints g(3)
g<int, int>(1, 1); // Prints g(3)
所有这些都可以在here - copied from @Yakk's comment Action 中看到。关于c++ - 如何确定功能特化的主要模板?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40284153/