- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
因此,我和一位同事一直在讨论显式模板实例化在减少编译时间、将声明与定义分开以及不影响我编写的用于其他项目的 C++ 数学库的性能方面的好处。
本质上,我有一个有用的数学函数库,旨在与 Vector3、Vector4、Quaternion 等原语一起使用。所有这些都用于模板参数为 float 或 double(在某些情况下为 int) .
这样我就不必将这些函数写两次,一次用于 float ,一次用于 double ,函数实现是模板化的,如下所示:
template<typename T>
Vector3<T> foo(const Vector4<T>& a,
const Quaternion<T>& b)
{ do something... }
全部在 .h 文件中定义(因此它们被隐式标记为内联)。这些函数大部分都很短,希望在使用编译时内联。
不过, header 变得越来越大,编译时间也在增加,并且越来越难以仅通过浏览 header 来找到函数的存在(这是我喜欢将声明与实现分开的众多原因之一)。
所以我可以在随附的 .cpp 文件中使用显式模板实例化,如下所示:
//in .h
template<typename T>
Vector3<T> foo(const Vector4<T>& a,
const Quaternion<T>& b)
{ do something... }
//in .cpp
template Vector3<float> foo<float>(const Vector4<float>& a,
const Quaternion<float>& b);
template Vector3<double> foo<double>(const Vector4<double>& a,
const Quaternion<double>& b);
这应该有助于编译时间?这会影响内联函数的可能性吗?这些问题中的任何一个的答案通常都是特定于编译器的吗?
一个额外的好处是它确实验证函数编译,即使我还没有使用它。
我也可以这样做:
//in .h
template<typename T>
Vector3<T> foo(const Vector4<T>& a,
const Quaternion<T>& b);
//in .cpp
template<typename T>
Vector3<T> foo(const Vector4<T>& a,
const Quaternion<T>& b)
{ do something... }
template Vector3<float> foo<float>(const Vector4<float>& a,
const Quaternion<float>& b);
template Vector3<double> foo<double>(const Vector4<double>& a,
const Quaternion<double>& b);
该方法的相同问题:
这应该有助于编译时间?这会影响内联函数的可能性吗?这些问题中的任何一个的答案通常都是特定于编译器的吗?
考虑到定义不在 header 中,我预计内联的可能性肯定会受到影响。
它很好地分离了模板化函数的声明和定义(针对特定的模板参数),而无需诉诸于使用包含在 .h 文件底部的 .inl 之类的操作。这也对库的用户隐藏了实现,这是有益的(但还不是绝对必要的),同时仍然能够使用模板,所以我不必实现一个函数 N 次。
有没有办法通过调整方法来允许内联?
我发现很难通过谷歌搜索这些问题的答案,并且很难理解这些主题的标准规范(至少对我而言)。
顺便说一句,这预计将使用 VS2010、VS2012 和 GCC 4.7 进行编译。
如有任何帮助,我们将不胜感激。
谢谢
最佳答案
我假设您的技术旨在与这个问题的答案相同:Template instantiation effect on compile duration
要达到预期的结果,您还需要通过使用 extern
在 header 中声明显式实例化来防止自动实例化。参见 Explicit instantiation declaration with extern
//in .h
template<typename T>
Vector3<T> foo(const Vector4<T>& a,
const Quaternion<T>& b);
extern template Vector3<float> foo<float>(const Vector4<float>& a,
const Quaternion<float>& b);
extern template Vector3<double> foo<double>(const Vector4<double>& a,
const Quaternion<double>& b);
//in .cpp
template<typename T>
Vector3<T> foo(const Vector4<T>& a,
const Quaternion<T>& b)
{ /* do something...*/ }
template Vector3<float> foo<float>(const Vector4<float>& a,
const Quaternion<float>& b);
template Vector3<double> foo<double>(const Vector4<double>& a,
const Quaternion<double>& b);
This should aid with compile times? Would this affect the possibility the possibility of the functions being inlined? Are the answers to either of those questions generally compiler specific?
答案在很大程度上取决于编译器 - 应该根据经验更准确地确定 - 但我们可以对其进行概括。
我们可以假设编译时间的增加不是来自解析额外的模板尖括号语法的成本,而是来自模板实例化的(复杂)过程的成本。如果是这种情况,那么在多个翻译单元中使用给定模板专门化的成本应该会显着增加编译时间,前提是实例化很昂贵并且编译器会多次执行实例化。
C++ 标准隐含地允许编译器在所有翻译单元中对每个唯一的模板特化执行一次实例化。也就是说,模板函数的实例化可以延迟并在初始编译后执行,如 Comeau 中所述。文档。是否实现此优化取决于编译器,但肯定不会在 2015 年之前的任何版本的 MSVC 中实现。
如果您的编译器在链接时执行实例化,如果编译器不支持跨模块内联,则此技术将阻止内联。较新版本的 MSVC、GCC 和 Clang 都支持在链接时使用附加链接器选项(LTCG 或 LTO)进行跨模块内联。参见 Can the linker inline functions?
关于c++ - 使用内联的显式模板函数实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26392876/
有没有一种方法可以使用标准类型构造函数(例如 int、set、dict、list、tuple 等)以用户定义的方式将用户定义类的实例强制转换为其中一种类型?例如 class Example:
我知道这个问题在Stackoverflow中有很多问题,但是即使有很多答案,这些答案也帮不了我什么,也没有找到答案。 在我的WebAPP中,它可以正常工作,但是当我将其转换为API时,它失败了(主题标
这个问题已经有答案了: Why does the ternary operator unexpectedly cast integers? (3 个回答) 已关闭 9 年前。 最近遇到一个Java的陷
我尝试使用 FirebaseApp.configure() 配置 Firebase,但遇到以下崩溃: *** Terminating app due to uncaught exception 'c
我有一个自连接员工实体类,其中包含与其自身相关的 id、name 和 ref 列。我想创建它的新实例并将其保存到数据库。 首先我创建了一个 Employee 类的实例并将其命名为 manager。然后
我有一个用于添加新公寓的表单,在该表单中我有一个下拉列表,用户可以在其中选择负责的人员。 显然,当您从下拉列表中选择并尝试保存公寓时,我的应用程序认为该人已被修改。它给了我下面的错误,指示我应该首先保
从 Visualforce 页面,我需要检索我们组织的 salesforce 实例的 URL,而不是 Visual Force URL。 例如我需要https://cs1.salesforce.com
我遇到了一些可能的问题答案,但这是关于从 Hibernate 3.4.0GA 升级到 Hibernate 4.1.8 的问题。所以这曾经在以前的版本下工作,我已经四处搜索了为什么它在这个新版本中出现了
似乎一遍又一遍地问这个问题,我仍然找不到解决我问题的答案。我在下面有一个域模型。每个新创建或更新的“安全用户”都需要我确保其具有配置文件,如果没有,则创建一个新的配置文件并分配给它。 配置文件的要求相
我很难调试为什么 JPA 不级联我的 @ManyToMany 关系。我发现的所有答案都与缺少级联语句有关。但我确实拥有它们并且仍然得到: Caused by: org.hibernate.Transi
Play 服务 API 表明有一个叫做 Instance ID 的东西 但是,在 Android Studio 中包含以下内容后,我无法导入 InstanceID 类 compile "com.goo
我正在使用 Seam 框架。我有 2 个实体: 请求.java @Entity @Table(name = "SRV_REQUEST") public class Request { private
This question处理构建一个适当的Monad来自单子(monad)的实例,但仅在某些约束下 - 例如Set .诀窍是将其包装成 ContT ,它将约束推迟到包装/展开其值。 现在我想对 Ap
我正在尝试执行此查询: StringBuffer sb = new StringBuffer(); sb.append("select p from PointsEntity p " + "where
我试图了解是否可以更改我的 hibernate 配置并使用单个 MySQL 实例(而不是我当前拥有的多个 MySQL 实例): 我有一个使用 hibernate 的 Java 应用程序,与 2 个模式
我有一个选项卡滑动布局,其中包括四个选项卡,每个选项卡都有自己的布局和 fragment ,在我的主要 Activity 布局中,viewpager 参与更改选项卡。特定 View (选项卡)在应用程
我看到很多帖子声称他们正在运行 MySql 的 RDS 实例,但无法连接到该实例,但我没有运行 RDS。 我使用 EC2 实例来托管我的 WordPress 博客,该博客是使用 Web 平台安装程序安
因为我在我的 ec-2 实例上的 python 虚拟环境中运行应用程序( Airflow ),并且我想在同一个 ec2 实例上的默认 python 环境中运行命令,所以我认为 ssh 到我自己的实例更
这个问题已经有答案了: How to fix the Hibernate "object references an unsaved transient instance - save the tra
例子: run APP1 .. ... run APP1 ... run APP2 如何在 APP2 中对 Vue 说我需要调用 APP1?
我是一名优秀的程序员,十分优秀!