函数模板专门化的主模板通常很直观,然而,我正在寻找形式规则来理解更令人惊讶的情况。例如:
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) {}
在推断要专门化哪个模板时,编译器将识别两个候选模板。然后,它必须选择最合适的。这种选择的过程称为“函数模板的偏序”。所选报价:
当同一函数模板专门化匹配多个重载函数模板时(这通常是模板参数推导的结果),将对重载函数模板执行偏序以选择最佳匹配。
让我们调用匹配模板集。然后,对于S中的每一对(f1,f2),编译器将通过在其类型(对应的非类型)参数上应用伪类型(对应的值)来转换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)
所有这些都可以在这里看到——摘自@Yakk的评论。
我有以下模板方法: 但是我得到了那些奇怪的链接错误: /usr/lib/gcc/x86_64-redhat-linux/4.4。7/../../../../包括/c/4.4。7/例外:62:void MyStruct::readField(std::basic_istream)的多重定义 如何专门化此成员函数? 编辑 这种方法在以下方面起作用: 或者使用s或在类外使用
在本文中,他们说(c)是(b)的显式专门化。我的疑问是,为什么我们不能说它是(a)的显式专门化?因为我们可以为任何特定类型专门化模板。所以,当专门化int*时,为什么他们说(c)显式专门化(b)。 任何评论都将有助于理解事情。
问题内容: 这是我的代码: 它运作良好。但是当我尝试添加这个 我遇到编译器错误:«int MyClass :: DoSomething()»的«>»令牌模板标识«DoSomething <0>»之前的无效显式专门化与任何模板声明都不匹配 我使用g ++ 4.6.1应该怎么做? 问题答案: 不幸的是,如果不对外部模板进行特殊化处理,就不能对作为类模板成员的模板进行特殊处理: C ++ 11 14.7
我有一个程序如下。有一个基本模板,以及SFINAE的部分专业化。 在2运行程序时,将打印 中的
顺便说一句,我确实编译了以下内容,但是专门化在运行时没有像预期的那样工作。基类型和派生类型最终要经历的非专用版本。 正确的语法是什么?
我试图编写一个可变函数模板来计算的字节大小。这将用于一个网络编程项目,我正在工作。第一步,我在没有工作的variadic模板的情况下想出了这个: 错误代码#2。如果我将variadic模板放在不同的位置: 我得到了 错误:重载的'size t ()'调用不明确