【问题标题】:Function Templates - Explicit specialisation vs Global Functions (C++)函数模板 - 显式特化与全局函数 (C++)
【发布时间】:2010-10-08 06:01:32
【问题描述】:

我知道使用 函数模板 是为了使函数具有可移植性,以便它们可以与任何数据类型一起使用。

如果我们对特定数据类型有更有效的实现,那么模板的显式特化也会完成。

但是,除了 Explicit Specialization,我们还可以编写一个 Nontemplate Function,它可以从 main 调用。 这将为我们节省一些处理时间,因为编译器会比 Explicitly Specialized Templated Functions 更快地定位 Nontemplate Functions,这反过来又会提高效率。

那么,当我们可以选择只调用非模板函数时,为什么还要使用显式特化

如果我错了,请纠正我!

编辑 1: 我的教授告诉我,每当我们制作函数模板并从 main 调用函数时,编译器首先会查找模板化函数,如果无法找到该函数,则它会依次搜索函数模板创建一个模板函数,然后调用它。

【问题讨论】:

  • 您是在 C++ 的上下文中说的吗?在这种情况下,重新标记问题以添加 C++ 标记。
  • @Naveen - 谢谢。我现在添加了 c++ 标签。
  • 当您说“全局函数”时,您的意思是“非模板函数”,对吧?

标签: c++ templates generics function-templates explicit-specialization


【解决方案1】:

这将为我们节省一些处理时间,因为编译器会比显式专用模板函数更快地定位全局函数,这反过来会在效率方面更好。

为什么编译器会比函数模板特化更快地找到非模板函数?您是否对编译器性能进行了基准测试以验证此声明?如果您使用名为 f 的函数,编译器总是必须编译一组候选函数并执行重载决策以确定要使用的正确函数。

在运行时(这才是性能真正重要的时候,对吧?)调用函数模板实例化的性能应该不会比调用非模板函数的性能好。

那么,当我们可以选择只调用全局函数时,为什么还要使用显式特化呢?

在一般情况下,对于函数模板,您不使用显式特化,因为它通常会令人困惑和困难。 ISO C++ 标准有一个诗意的警告,即在特化函数模板时要格外小心。您可以阅读 Herb Sutter 的 "Why Not Specialize Function Templates?",以很好地解释这些问题以及您为什么不想专门化函数模板。

【讨论】:

  • 大多数函数模板永远不会被特化,这是真的,但大多数时候程序员必须重写函数模板的行为,他们会特化模板而不是引入新的重载,因为您可以在namespace std 中进行专业化,但该标准不允许新的重载。 std::swap 可能足以打破平衡。
  • @Ben: std::swap 不需要专门化;我见过的实现高效交换的首选方法是将其作为非成员函数与相关类一起实现,并让 ADL 找到它(std::swap 可以用作后备方法,在调用 @ 之前使用 using std::swap 987654330@).
  • @James:在这种情况下,<algorithm> 找不到自定义的swap。最好的方法是实现你自己的swap 作为一个特化(如果你需要一个后备案例,可能是错误的,无论如何默认是微不足道的),并在你自己的命名空间中放置一个存根函数来调用它。或相反亦然。无论哪种方式,都可以两全其美。
  • @Potatoswatter:std 命名空间中的标准库函数应引用不合格的swap(即swap(x, y) 而不是std::swap(x, y))。这样,如果您有 namespace N { class C { }; void swap(C&, C&); } 并且标准库函数有两个需要交换的 C 对象 (C x, y; swap(x, y);),ADL 会确保调用 N::swap(),而不是 std::swap()
  • 虽然,从 2000 年开始,有194 comp.lang.c++.moderated posts 争论,其中哪一个是更好的方法。 Dave Abrahams recommends nonmember-function-alongside-the-class 方法。
【解决方案2】:

听起来您将编译时效率与运行时效率混淆了。调用哪个函数的选择是在编译时做出的,而不是在运行时进行的,因此对程序的运行时间没有影响。

当您有可以从特殊处理中受益的特殊情况时,使用显式专业化。有时这会适得其反,例如std::vector<bool>,而其他时候却很方便。这意味着函数的用户不需要知道有特殊情况;它只是透明的。

【讨论】:

  • 是的,因为我们的教授告诉我们,这需要更多的处理时间。无论如何,现在我明白了,谢谢。 +1
【解决方案3】:

出于统一的原因。使用 API 的人只需调用具有特定参数的方法,一些获取通用函数,一些获取明确的专用函数 - 客户端不需要知道也不需要关心他们使用哪个。

【讨论】:

  • 您可能还应该指出他实际上是错误的:全局函数也不会更有效。
  • 不过,API 的使用者并不关心。函数重载,同名的函数和函数模板都可以在名称解析过程中找到,并且都可以在重载解析过程中被视为候选。 API 的使用者很少会关心,例如,是否显式使用了函数模板(例如,f<>(x) 而不是 f(x))或者是否无法从函数参数中推导出某些模板参数(在这种情况下消费者必须决定无论如何要做什么)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-27
  • 2019-04-15
  • 2011-01-07
相关资源
最近更新 更多