【发布时间】:2017-03-09 22:23:27
【问题描述】:
在 C++03 中,我们有模板显式实例化定义 (template class Foo<int>),它强制实例化模板类。
在 C++11 中,我们有 模板显式实例化声明 (extern template class Foo<int>),它可以防止模板类的隐式实例化。 (Class template instantiation)
我正在尝试模拟实际需要显式实例化声明以减少编译时间的情况。但我不能。没有此功能(或无法使用)似乎一切正常。
这是一个例子:
//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 template class Foo<int>;) 行。
这是两个 *.obj 文件的符号:
dumpbin /SYMBOLS test1.obj
011 00000000 UNDEF notype () 外部 | ??0?$Foo@H@@QAE@H@Z (public: __thiscall Foo::Foo(int))'
012 00000000 UNDEF notype () 外部 | ?get@?$Foo@H@@QBEHXZ (public: 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 (public: __thiscall Foo::Foo(int))
018 00000000 SECT6 notype () 外部 | ?get@?$Foo@H@@QBEHXZ (public: int __thiscall Foo::get(void)const )
注意 Foo<int>::Foo<int>(int) 和 int Foo<int>::get(void)const 在 test1.obj 中标记为 UNDEF 的内容,这意味着它们必须在其他地方解析(即 Foo 仅编译一次)。
尝试 #2:
如果我在 Foo.h 文件中定义完整模板(没有显式实例化定义),那么 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 (public: __thiscall Foo::Foo(int))
01E 00000000 SECT8 notype () 外部 | ?get@?$Foo@H@@QBEHXZ (public: 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 (public: __thiscall Foo::Foo(int))
01F 00000000 SECT8 notype () 外部 | ?get@?$Foo@H@@QBEHXZ (public: int __thiscall Foo::get(void)const )
在 Foo 提供的两个 *.obj 文件中。
所以我的问题是显式实例化声明可能有什么用处?或者我在测试中遗漏了什么?
我使用VS2013编译器。
【问题讨论】:
标签: c++11 templates extern explicit-instantiation