当前位置: 首页 > 知识库问答 >
问题:

函数模板显式专门化

狄灵均
2023-03-14

在本文中,他们说(c)是(b)的显式专门化。我的疑问是,为什么我们不能说它是(a)的显式专门化?因为我们可以为任何特定类型专门化模板。所以,当专门化int*时,为什么他们说(c)显式专门化(b)。

template<class T>   // (a) a base template 
void f( T );

template<class T>   // (b) a second base template, overloads (a) 
void f( T* );       //     (function templates can't be partially 
                //     specialized; they overload instead)

template<>          // (c) explicit specialization of (b) 
void f<>(int*);

任何评论都将有助于理解事情。

共有1个答案

云星波
2023-03-14

如果(b)不存在,那么(c)将确实是(a)的有效专业化。事实上,只要改变源代码行的顺序,使(c)在编译器看到(b)之前出现,就会使它成为(a)的一种特殊化!

考虑以下代码:

int main()
{
    int a;
    f(&a);
    return 0;
}

现在设身处地为编译器着想。您需要找到一个带有int*参数的匹配函数f。你会怎么做?

  • 首先,尝试所有已知的名为f的非模板函数,看看是否有与参数类型匹配的函数(在本例中为int*
  • 如果你不能得到一个完美的匹配,你可以查看所有你知道的基本模板。在这种情况下,有两种:f

有趣的是。如果我们更改原始代码的顺序

template<class T> void f( T ); // (i)

template<> void f<>(int*); // (ii)

template<class T> void f( T* ); // (iii)

然后,编译器现在将(ii)视为(i)的专门化——因为它按顺序处理事物,在到达(ii)时,它还不知道(iii)的存在!但是因为它只匹配基本模板,所以它决定(iii)比(i)更匹配——现在(iii)没有任何专门化,所以得到了默认的实例化。

这一切都非常令人困惑,有时甚至会让最有经验的C程序员绊倒。所以基本规则是:不要专门化函数模板,而是使用普通函数重载。一个普通的旧的非模板

void f(int*);

在其他任何事情之前都会被匹配,并避免整个混乱。

编辑:n. m.要求在评论中引用标准。恐怕我手头只有C 03版本,但这里有:

第4.7.3.3段:“明确专门化的函数模板或类模板的声明应在明确专门化声明点的范围内。”。

这就是为什么在上面的例子中,(ii)不能被视为(iii)的明确专业化,因为(iii)还不在范围之内。

第4.8.3节:“当编写对该[函数]名称的调用时......对每个函数模板执行模板参数推导(14.8.2)和任何显式模板参数检查(14.3),以查找可与该函数模板一起使用的模板参数值(如果有),以实例化可以使用调用参数调用的函数模板特化。”

换句话说,(正如我所读到的那样),不管发生什么,它都会查看每个基本模板——提供明确的专业化并没有什么区别。

同一段继续:“对于每个函数模板,如果参数推导和检查成功,则模板参数(推导和/或显式)用于实例化单个函数模板特化,该特化被添加到候选函数集中用于重载解析。”

因此,只有在这一点上(正如我所读到的),明确的专业化才能得到考虑。

最后,也许在这种情况下最重要的是,第13.3.3节涉及在过载集中选择“最佳可行函数”。有两项是相关的:

>

F1比F2更好,如果:“F1是一个非模板函数,F2是一个函数模板专门化”,这是我在原始答案末尾给出建议的基础。

唷!

 类似资料:
  • 我想用两种模板类型编写一个模板化函数:一种是bool,另一种是typename,我想专门研究typename。 这就是我想要的,但只针对T的几种类型: 没有bool在那里,我可以做这样的事情: 我搞不懂这句话的语法,而专门化方面的微软文档只涉及单一类型的情况。

  • 我试图编写一个可变函数模板来计算的字节大小。这将用于一个网络编程项目,我正在工作。第一步,我在没有工作的variadic模板的情况下想出了这个: 错误代码#2。如果我将variadic模板放在不同的位置: 我得到了 错误:重载的'size t ()'调用不明确

  • 我有以下模板方法: 但是我得到了那些奇怪的链接错误: /usr/lib/gcc/x86_64-redhat-linux/4.4。7/../../../../包括/c/4.4。7/例外:62:void MyStruct::readField(std::basic_istream)的多重定义 如何专门化此成员函数? 编辑 这种方法在以下方面起作用: 或者使用s或在类外使用

  • 现在我想将它专门化为一个特定的值: 这无法用(版本4.6、4.7、4.8和4.9)编译: 不同命名空间中“template void foo::function()”的专门化[-fpermissive]

  • 我有一段代码,它是做模板专门化的常用模式。为了移除main函数第一行中为Processor1指定DataType1的要求,我想改为接收一个template模板参数。看起来using指令不支持分配“open”模板参数,而且我在web中找不到任何这样的示例(可能我没有使用适当的关键字进行搜索...) 所以问题很“简单”,我如何让这段代码编译呢?在FindDefaultProcessor中,使用type