C++11 外部模板:我们在哪里真正需要它们?

2024-01-29

在 C++03 中我们有模板显式实例化定义 (template class Foo<int>) 强制实例化模板类。

在 C++11 中我们有模板显式实例化声明 (extern template class Foo<int>)这应该防止模板类的隐式实例化。 (类模板实例化 http://en.cppreference.com/w/cpp/language/class_template)

我试图模拟我实际上需要显式实例化声明以减少编译时间的情况。但我不能。看起来没有这个功能一切都可以工作(或者不使用它)。

这是一个例子:

//Foo.h
#pragma once
template<class T>
class Foo
{
    T inst;
public:
    Foo(T i);
    T& get() const;
};


//Foo.cpp
#include "stdafx.h"
#include "Foo.h"

template<class T>
Foo<T>::Foo(T inst) : inst(inst) { }

template<class T>
T& Foo<T>::get() const { return inst; }

template class Foo<int>; //explicit instantiation definition


//test1.h
#pragma once
#include "Foo.h"

//This line does not work
//extern template class Foo<int>; //explicit instantiation declaration.

void baz();


//test1.cpp
#include "stdafx.h"
#include "test1.h"

void baz()
{
    Foo<int> foo(10);
    int i = foo.get();
}

结果does not取决于我是否评论(extern template class Foo<int>;)行与否。

以下是两个 *.obj 文件的符号:

dumpbin /SYMBOLS test1.obj

011 00000000 UNDEF notype () 外部 | ??0?$Foo@H@@QAE@H@Z(公共:__thiscall Foo::Foo(int))'

012 00000000 UNDEF notype () 外部 | ?get@?$Foo@H@@QBEHXZ (公共:int __thiscall Foo::get(void)const )

013 00000000 SECT4 notype () 外部 | ?baz@@YAXXZ (void __cdecl baz(void))

...

dumpbin /SYMBOLS Foo.obj

017 00000000 SECT4 notype () 外部 | ??0?$Foo@H@@QAE@H@Z(公共:__thiscall Foo::Foo(int))

018 00000000 SECT6 notype () 外部 | ?get@?$Foo@H@@QBEHXZ (公共:int __thiscall Foo::get(void)const )

注意什么Foo<int>::Foo<int>(int) and int Foo<int>::get(void)const标记为UNDEF在 test1.obj 中,这意味着它们必须在其他地方解析(即 Foo 仅编译一次)。

尝试#2:

如果我在 Foo.h 文件中定义完整模板(without显式实例化定义)然后extern template没有帮助 - 模板编译两次(在 test1.cpp 和 test2.cpp 中)。

例子:

//test1.h
#pragma once
#include "Foo.h"
void baz();


//test1.cpp
#include "stdafx.h"
#include "test1.h"
void baz()
{
    Foo<int> foo(10); //implicit instantiation of Foo<int>
    int i = foo.get();
}


//test2.h
#pragma once
#include "Foo.h"
extern template class Foo<int>;
void bar();


//test2.cpp
#include "stdafx.h"
#include "test2.h"
void bar()
{
    Foo<int> foo(10); //should refer to Foo<int> from test1.obj but IT IS NOT
    int i = foo.get();
}

以下是符号转储:

dumpbin /SYMBOLS test2.obj

01D 00000000 SECT4 notype () 外部 | ??0?$Foo@H@@QAE@H@Z(公共:__thiscall Foo::Foo(int))

01E 00000000 SECT8 notype () 外部 | ?get@?$Foo@H@@QBEHXZ (公共:int __thiscall Foo::get(void)const )

01F 00000000 SECT6 notype () 外部 | ?bar@@YAXXZ (void __cdecl bar(void))

dumpbin /SYMBOLS test1.obj

01D 00000000 SECT6 notype () 外部 | ?baz@@YAXXZ (void __cdecl baz(void))

01E 00000000 SECT4 notype () 外部 | ??0?$Foo@H@@QAE@H@Z(公共:__thiscall Foo::Foo(int))

01F 00000000 SECT8 notype () 外部 | ?get@?$Foo@H@@QBEHXZ (公共:int __thiscall Foo::get(void)const )

在 Foo 提供的两个 *.obj 文件中。

所以我的问题是显式实例化声明的用处是什么?或者也许我在测试中遗漏了一些东西?

我用的是VS2013编译器。


这是为什么 ATTEMPT#2 不能按我想要的方式工作的一个很好的解释:Visual C++ 中的 extern 模板是否存在错误? https://stackoverflow.com/questions/12650737/is-there-a-bug-with-extern-template-in-visual-c

简而言之,当您在头文件中定义和实现模板时,编译器可能会内联它。然后它执行显式实例化定义按标准不起作用(14.7.2/10“显式实例化”)。

所以我们需要强制编译器不内联模板。例如,在声明之后立即实施它。

template<class T>
class Foo {
   ...
   T get() const;
};

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

C++11 外部模板:我们在哪里真正需要它们? 的相关文章

随机推荐

  • 在python中提取分隔符[]之间的单词

    从下面的字符串中 我想提取分隔符之间的单词 like Service Current Service 9991 1 22 str mysrv events Generating Event Name Service Current Cate
  • 在 NSPredicate 中组合“AND”和“OR”条件

    再次回来需要更多帮助来构建我的 NSPredicates Category name string subs lt gt gt SubCategory SubCategory name string numbervalue NSNumber
  • 每个帖子有多个例外,并带有摘录类别

    我正在寻找一种解决方案 允许自定义帖子类型中的每个帖子有多个摘录框 并且有一种方法可以让这些摘录具有类别 我知道我可以添加元框来提供额外的文本区域并显示该文本 但我不太确定这就是我想要的 澄清一下 我有一个自定义的推荐帖子类型 该帖子类型具
  • 是否可以使用 MediaRecorder() 获取音频数据的原始值

    我使用 MediaRecorder 和 getUserMedia 来记录浏览器中的音频数据 它可以工作 但是记录的数据是以 Blob 格式记录的 我想获取原始音频数据 振幅 而不是 Blob 有可能做到吗 我的代码如下所示 navigato
  • 如何从类方法中调用全局函数

    我有以下代码 def static func name print Name name class A def init self name self name name def fun self static func self name
  • GWT MVP - 维护多个彼此独立的显示

    我有一个 GWT 应用程序 并且正在将 GWT MVP 与地点 活动一起使用 我的应用程序布局是这样的 菜单 内容 菜单和内容显示将动态变化 并且其中一个变化独立于另一个 我的意思是 当内容显示发生变化时 我不想更新菜单显示 反之亦然 两个
  • typeof(DateTime?).Name == Nullable`1

    在 Net 中使用反射typeof DateTime Name返回 可空 1 有什么方法可以将实际类型作为字符串返回 在本例中为 DateTime 或 System DateTime 我明白那个DateTime is Nullable
  • 如何在 iOS 中向 PHP 发送 GEt 请求

    您好 我在向 PHP 发送 GET 请求时遇到问题 相同的 PHP 在 Web 浏览器中运行时工作正常 这是 PHP 和 Obj C 的代码片段 PHP var1 GET value1 var2 GET value2 当我在浏览器中调用它时
  • Android 项目的 tab+swipe 应用程序中不同选项卡的不同菜单

    我是 android 应用程序和 java 的初学者 基本上我是 PHP 开发人员 我有一个选项卡 滑动应用程序的项目 经销商 java 在 res menu 文件夹中为 menu a xml 和 menu b xml 创建菜单 xml 文
  • CoreData - 将实体的属性设置为不为空 - 属性应该设置为可选还是强制

    我需要将 Coredata 实体中的一个属性设置为非空并具有默认值 我已在 xcdatamodeld 架构定义中为实体的属性设置了默认值 我的问题是该属性是否应该标记为可选 如果我不检查属性的以下三个属性 Transient Optiona
  • 如何在sql server中选择彼此相隔一小时的记录

    我有一组带有时间戳的 user id 登录数据 用户可以多次登录 但我们需要从最短记录开始返回至少相隔一小时的记录 重复数据删除必须在用户级别进行 可以有多个用户 for eg 用户1 2012 03 07 14 24 30 000 用户1
  • 使用javascript获取外部url的文档

    我有一个 html 表单 它接受 url 作为 txt 输入和提交按钮 当我单击按钮时 我想访问提供的 url 的文档模型 我如何使用 javascript 访问该 url 的文档 如果您向该 url 发出 HTTP GET 请求 您将收到
  • std::initializer_list 作为构造函数的模板参数

    考虑一个从 std 容器继承的类 其模板构造函数调用容器的底层构造函数 此模板构造函数适用于简单的复制和移动构造函数 但不适用于initializer list 构造函数 template
  • DT:根据 R 闪亮应用程序中另一列的选择输入动态更改列值

    我正在尝试创建一个表 使用 DT 请不要使用 rhandsontable 该表几乎没有现有列 一个 selectinput 列 其中每行都有可供选择的选项 最后是另一列 该列将根据用户选择的内容进行填充从每行的 selectinput 下拉
  • 为什么 Internet Explorer 8 中会出现此泄漏?

    为什么下面的代码会泄漏 for var i 0 i lt 100 i var item item elem document createElement div document body appendChild item elem ite
  • 带请求正文的 Elasticsearch GET 请求

    将请求正文与 GET 请求一起传递不是违反 REST 风格的方法吗 例如在Elasticsearch中过滤一些信息 curl localhost 9200 megacorp employee search d query filtered
  • iTextSharp 5 波兰语字符

    我在使用 itextSharp 处理波兰语字符时遇到问题 我想从 html 创建 pdf 一切都很好 但缺少波兰特色 我使用较低的功能 private void createPDF string html MemoryStream msOu
  • 在 Common Lisp 中替换列表中的项目?

    我有一个事物列表 我称之为 L 一个索引 N 和一个新事物 NEW 如果我想用 NEW 替换 L 中 N 中的内容 最好的方法是什么 我是否应该获取到 N 的子列表以及从 N 到列表末尾的子列表 然后使用列表将第一部分 NEW 和最后一部分
  • Prometheus 标签与矢量时间戳的比较

    我有一个像 T V label UTCtimestamp 这样的向量 其中 label UTC 时间戳字符串 我想找到具有类似标签的所有向量的计数 T 1day 其中 T 是 Vector 被推送的时间戳 我正在寻找一些查询 例如 V T
  • C++11 外部模板:我们在哪里真正需要它们?

    在 C 03 中我们有模板显式实例化定义 template class Foo