GCC 和 MS 编译器的模板实例化详细信息

2023-12-05

任何人都可以提供模板实例化方式的比较或具体细节吗 在 GCC 和 MS 编译器中的编译和/或链接时处理?这个过程有什么不同吗 在静态库、共享库和可执行文件的上下文中? 我发现this doc关于 GCC 如何处理它,但我不确定这些信息是否 仍然指的是事情的现状。我应该使用标志吗 他们在编译我的库时建议在那里,例如-fno-隐式模板?

我所知道的(不一定正确)是:

  • 模板在实际使用时会被实例化
  • 模板将作为显式实例化的结果而被实例化
  • 重复实例化通常通过折叠重复实例化或将实例化推迟到链接时间来处理


实例化点

模板在实际使用时会被实例化

不完全是,但大概是这样。实例化的精确点有点微妙,我将您委托给名为的部分实例化点在 Vandevoorde/Josuttis 的好书中。

然而,编译器不一定正确实现 POI:Bug c++/41995:函数模板的实例化点不正确


部分实例化

模板在实际使用时会被实例化

这是部分正确的。对于函数模板来说确实如此,但是对于类模板来说,只有所使用的成员函数才会被实例化。以下是格式良好的代码:

#include <iostream>

template <typename> struct Foo {
    void let_me_stay() {
        this->is->valid->code. get->off->my->lawn;
    }

    void fun() { std::cout << "fun()" << std::endl; } 
};


int main () {
    Foo<void> foo;
    foo.fun();
}

let_me_stay()在语法上进行检查(并且那里的语法是正确的),但不在语义上检查(即不解释)。


两阶段查找

然而,仅相关代码稍后解释;显然,在Foo<>, this取决于具体的 template-idFoo<>已实例化,因此我们推迟了错误检查Foo<>::let_me_alone()直到实例化时间。

但如果我们不使用依赖于具体实例化的东西,代码一定是好的。因此,以下是not格式良好:

$ cat non-dependent.cc
template <typename> struct Foo {
    void I_wont_compile() { Mine->is->valid->code. get->off->my->lawn; }
};
int main () {} // note: no single instantiation

Mine与编译器不同的是,它是一个完全未知的符号this,编译器可以确定它的实例依赖性。

这里的关键点是 C++ 使用的模型两阶段查找,它在第一阶段检查非依赖代码,而对依赖代码的语义检查在第二阶段(和实例化时间)完成(这也是一个经常被误解或未知的概念,许多 C++ 程序员认为模板不是直到实例化才进行解析,但这只是来自……Microsoft C++ 的神话)。


类模板的完整实例化

的定义Foo<>::let_me_stay()有效,因为错误检查被推迟到以后,至于this指针,它是依赖的。除非你会使用

显式实例化

cat > foo.cc
#include <iostream>

template <typename> struct Foo {
    void let_me_stay() { this->is->valid->code. get->off->my->lawn; }
    void fun() { std::cout << "fun()" << std::endl; } 
};

template struct Foo<void>;
int main () {
    Foo<void> foo;
    foo.fun();
}

g++ foo.cc
error: error: ‘struct Foo<void>’ has no member named ‘is’


不同翻译单位的模板定义

当您显式实例化时,您就显式实例化。和做all链接器可见的符号,这也意味着模板定义可能驻留在不同的翻译单元中:

$ cat A.cc
template <typename> struct Foo {
    void fun();  // Note: no definition
};
int main () {
    Foo<void>().fun();
}

$ cat B.cc
#include <iostream>
template <typename> struct Foo {
    void fun();

};
template <typename T>
void Foo<T>::fun() { 
    std::cout << "fun!" << std::endl;
}  // Note: definition with extern linkage

template struct Foo<void>; // explicit instantiation upon void

$ g++ A.cc B.cc
$ ./a.out
fun!

但是,您必须显式实例化所有要使用的模板参数,否则

$ cat A.cc
template <typename> struct Foo {
    void fun();  // Note: no definition
};
int main () {
    Foo<float>().fun();
}
$ g++ A.cc B.cc
undefined reference to `Foo<float>::fun()'

关于两阶段查找的小注意事项:编译器是否真正实现两阶段查找并不是由标准规定的。然而,为了保持一致,它应该像它那样工作(就像加法或乘法不一定必须使用加法或乘法 CPU 指令来执行一样。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GCC 和 MS 编译器的模板实例化详细信息 的相关文章

随机推荐

  • Keras 中的多维输入层

    Keras 中的哪些层可以用作第一层来获取多维特征 我想使用具有 11 个通道的 1275 个特征的密集层 但看起来我只能对 2 维或更多维度的特征使用卷积层或循环层 那是对的吗 据我所知 您是正确的 但您可以将数据重塑为具有 1275 1
  • 类型类约束可以用在新类型定义中吗?

    假设我们有以下内容newtype定义 newtype A A run Monad m gt A gt Int gt m Int 这不能与 GHC 8 0 2 一起编译 error Not in scope type variable m 更
  • Struts2:如何为选择标签中的每个下拉选项显示工具提示?

    我有这个 struts2 选择标签 其中选项是 Item 对象的列表 假设 Item java bean 类具有以下 3 个属性 itemId itemLabel itemDescription 我的选择标签如下所示
  • 如何在 C++ 中构建动态数组并将其返回给 C#/.NET

    我必须找到在 C Win32 端构建结构数组的方法 我没有初始数量的物品 调整该数组的大小应该非常快 构建列表后 我需要将其返回到 NET 因此 该数组 列表 应该转换为可以在 NET 端轻松读取的传输方式 或者可以 按原样 使用初始列表
  • 与枚举一起使用

    我有一个 JSP portlet 需要根据枚举类型的 bean 属性的值显示不同的标记 public enum State CANCELED COMPLETED 我使用以下代码来进行切换
  • mini_magick gem 不适用于我的 ImageMagick 安装

    我通过 MacPorts 和 mini magick gem 安装了 ImageMagick 并且收到以下脚本的错误 我该如何解决这个问题 require rubygems require mini magick image MiniMag
  • 如何在 Visual Studio 中显示交互式 Holoviews 图表(无需 Jupyter)?

    在使用 Holoviews 进行交互式绘图时 我主要使用 Jupyter Notebook Lab 如何让 Visual Studio 显示交互式图形和面板 而不使用 Visual Studio 中的交互式 Jupyter 在 Visual
  • NodeJS Web服务器“未定义不是一个函数”

    我刚刚浏览了一本书 pro Angularjs 中的教程 并且在设置 Nodejs Web 服务器时遇到了一些问题 就像书中描述的那样 我使用以下 server js 来创建它 var connect require connect con
  • R:将解释变量的动态数量拟合到多项式回归中

    假设给我一个数据框df在运行时 如何使用多项式回归拟合多项式模型 每个预测变量都是 df 中的一列 并且常数 k gt 2 的程度 困难在于 df 是在运行时读取的 因此在编写脚本时其列的数量和名称是未知的 但我确实知道响应变量是第一列 所
  • 解析类似 XML 的日志文件

    我有一个日志文件 记录事件如下 我想将每个事件转换为 PSCustomobject 它看起来有点像 XML 但将 xml 转换为文件的 Get Content 会出现错误 无法将值 System Object 转换为类型 System Xm
  • 如何检测 Botframework v4 中的对话结束?

    我试图在系统中的任何其他对话框完成后启动反馈对话框 我发现这个答案上面说要使用onEndDialog 但这不是 ActivityHandler 中的有效函数 只是onDialog 我的 主对话框 位于扩展 ActivityHandler 的
  • 在 MVC 3 应用程序中为模型中的对象属性创建视图?

    我有一个 Asp Net MVC 3 应用程序 其中包含一个由 EF 访问的数据库 Consultants 现在 数据库中的顾问表与其他几个表存在一对多关系 以获取简历类型信息 工作经验等 因此 用户应该能够填写一次他们的姓名等 但应该能够
  • pandas 中独立的多头列数据框

    请帮助将这个多帧熊猫分成单独的部分 这就是代码 import datetime as dt import pandas as pd import pandas datareader data as web pd set option dis
  • Android,以编程方式上传照片到 imgur 上托管

    我尝试了不同的方法来通过 imgur 上传和检索链接 但尽管查看了 imgur api 但没有一个成功 http api imgur com examples uploading java 但以下方法部分有效 我试图找回 错误 如果发生任何
  • Android 中连续的“Action_DOWN”

    Override public boolean onTouchEvent MotionEvent event if event getAction MotionEvent ACTION DOWN Log d VIEW LOG TAG Tou
  • Qt:使用二维数组值更新像素图网格布局

    我正在使用 Visual Studio 2010 和 Qt 4 7 都是 Windows 中的 C 组合进行游戏 该游戏是战舰的克隆 基于控制台输入 我已经按照我想要的样子创建了 gui 在 Qt 设计器的 Qt 端 我的 gui 由一个
  • 无法将 Entity Framework Core 迁移添加到 .NET Standard 2.0 项目

    我有一个包含许多项目的解决方案 其中之一 Domain 是一个 NET Standard 2 0 项目 我在其中创建了 EF CoreDbContext我想要启用的实现数据库迁移 我看到了各种博客和问答论坛 其中解释了问题 但由于 NET
  • 谷歌驱动器分页不起作用。清空 nextPageToken

    我正在 Symfony 中使用 Google Drive API 该库包含在以下行中composer json google apiclient 2 2 代码如下 service new Google Service Drive googl
  • 如何结合多处理和 eventlet

    我有一个任务需要启动 2 个进程 并且每个进程内需要启动 2 个线程才能真正工作 下面是我用来模拟我的用例的源代码 import multiprocessing import eventlet def subworker num1 num2
  • GCC 和 MS 编译器的模板实例化详细信息

    任何人都可以提供模板实例化方式的比较或具体细节吗 在 GCC 和 MS 编译器中的编译和 或链接时处理 这个过程有什么不同吗 在静态库 共享库和可执行文件的上下文中 我发现this doc关于 GCC 如何处理它 但我不确定这些信息是否 仍