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

C 11 外部模板:我们在哪里实际需要它们?

艾善
2023-03-14

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

在 C 11 中,我们有模板显式实例化声明(extern 模板类 Foo

为了减少编译时间,我试图模拟实际需要显式实例化声明的情况。但是我不能。看起来所有东西都没有这个功能(或者没有这个功能)。

下面是一个例子:

//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();
}

结果不取决于我是否注释(extern 模板类 Foo

这是两者的符号。对象文件:

dumpbin /SYMBOLS test1.obj

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

012 00000000 UNDEF notype () external | ?get@?$Foo@H@@QBEHXZ (public: int __thiscall Foo::get(void)const )

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

...

dumpbin /SYMBOL Foo.obj

017 00000000 section 4 notype()External |??0?$ Foo @ H @ @ QAE @ H @ Z(public:_ _ this call Foo::Foo(int))

018 00000000第6节notype()外部|?明白了吗?$Foo@H@@QBEHXZ(公共:int__thiscall Foo::get(void)const)

注意什么 Foo

如果我在Foo. h文件中定义了完整的模板(没有显式的实例化定义),那么extern模板没有帮助-模板编译两次(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 section 4 notype()External |??0?$ Foo @ H @ @ QAE @ H @ Z(public:_ _ this call Foo::Foo(int))

01E 00000000第8节notype()外部|?明白了吗?$Foo@H@@QBEHXZ(公共:int__thiscall Foo::get(void)const)

01F 00000000第6节notype()外部|?bar@@YAXXZ(void__cdecl-bar(void))

dumpbin /SYMBOLS test1.obj

01D 00000000 section 6 notype()External |?baz@@YAXXZ (void __cdecl baz(void))

01E 00000000 section 4 notype()External |??0?$ Foo @ H @ @ QAE @ H @ Z(public:_ _ this call Foo::Foo(int))

01F 00000000 Sect 8 notype()External |?get@?$ Foo @ H @ @ QBEHXZ(public:int _ _ this call Foo::get(void)const)

在两个*中。Foo呈现的对象文件

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

我使用VS2013编译器。


共有1个答案

东方嘉佑
2023-03-14

这里有一个很好的解释为什么ATTEMP#2不能按照我想要的方式工作:Visual C中是否存在extern模板的错误?

简而言之,当您在头文件中定义和实现模板时,编译器可以将其内联。然后,显式实例化定义不按标准方式工作(14.7.2/10“显式实例化”)。

因此,我们需要强制编译器不内联模板。例如,通过在声明之后立即实现它。

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

template<class T>
T Foo<T>::get() const
{ ... }
 类似资料:
  • 我在Spring重新认识了豆子的不同范围。 每次我在xml中创建bean时,我都从未使用scope属性,这意味着它是单例的。" 对于原型,我读到“有状态bean首选原型范围” 有状态bean是什么意思?谁能给我一个实时的例子,我们在哪里有原型范围?

  • 在中有一个新控件,名为。下面是它的图片。 它的描述是 为外部故事板中的视图控制器提供占位符。连接到此占位符的Segue将在运行时实例化引用的视图控制器。 所以问题是 在什么情况下我们应该使用这个 这是否用于通过segue连接两个故事板的视图控制器 这种方法是否用于以编程方式替代另一个故事板的VC 它能在旧的iOS版本(iOS 9之前)上工作吗

  • 考虑一个无状态EJB 从EJB3.1规范中 容器将支持并发执行的会话 bean的许多实例;但是,每个实例只看到一个 序列化的方法调用序列。因此,有状态或 无状态会话bean不必被编码为可重入的 因此无状态seession bean一次最多只能“服务”一个请求,这通常是由管理bean池的容器实现的。这一切的伟大目标是线程安全。 我的问题是为什么我们需要这种形式的线程安全?我的意思是Spring be

  • 问题内容: 我相信大家都知道setUp(@Before)将在任何测试方法之前执行,而tearDown(@After)将在测试方法之后执行。 我们也知道Junit会为 每个测试方法 创建一个Test实例。 我的问题是,我们可以只将setUp方法的内容移至类Constructor并删除setUp方法吗?是否有任何特定理由保留setUp方法? 问题答案: 这篇(旧的)JUnit最佳实践文章将其描述如下:

  • 我非常了解minimax和alpha-beta修剪在返回“最佳值”方面的工作原理。然而,我不确定“最佳行动”应该分配到哪里。 我知道最好的动作需要来自传入的原始棋盘,因为我正在寻找一个最大值,所以它必须在最大化玩家下分配。然而,使用我当前的代码会导致最佳动作被一次又一次地重新分配。 例如,如果原始棋盘是O-\n---\n---,那么最佳动作就变成了 OX-\n---\n---,然后重新分配给O-X

  • 问题内容: 好的,假设我们有两个表,和。在评论中,我们有一列,它表示哪个用户键入了该特定评论。为什么我们需要将其指定为外键?如果我们不这样做,它将仍然有效。我们指定主键,因为据我所知,它可以使查询速度更快(我们只需要搜索一行,而当我们没有主键/索引时,则必须遍历所有行)。这只是一种良好的编码习惯吗? 问题答案: 使用外键时,您将获得: 数据的完整性 更快的查询。 用户: 用户ID: 1个 2个 3