【问题标题】:Why won't "extern template" work with shared_ptr?为什么“外部模板”不能与 shared_ptr 一起使用?
【发布时间】:2014-06-18 03:46:20
【问题描述】:

我有一个(看似)聪明的想法,即在 #include <memory> 之后立即在 stdafx.h 中使用 extern template class std::shared_ptr<SomeWidelyUsedClass>,以防止 std::shared_ptr<SomeWidelyUsedClass> 在数百个文件中被冗余实例化,我想我可以将 template class std::shared_ptr<SomeWidelyUsedClass> 放在单个 .cpp 以强制进行单个实例化并希望节省编译/链接时间。然而,对生成的 .cod 和 .obj 文件的检查表明,shared_ptr<SomeWidelyUsedClass> 代码无论如何都在到处创建。但是,如果我在自己的模板类中使用这种完全相同的技术,它就会按预期工作。 shared_ptr 有什么特别的地方排除了这种用途吗?也许<memory> 本身中的某些东西会强制编译器在它到达我的extern template 语句之前创建一个实例化(我很确定stdafx.h 中没有任何更高的东西使用shared_ptr)?

澄清一下:

// stdafx.h; included in every cpp in the project
#include <memory>
#include "SomeWidelyUsedClass.h" // no shared_ptr in here

// I expect this to prevent instantiation of std::shared_ptr<SomeWidelyUsedClass>
// in all compilation units that include this, except the one below.
extern template class std::shared_ptr<SomeWidelyUsedClass>;

然后:

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

// I expect this to cause std::shared_ptr<SomeWidelyUsedClass>
// to be instantiated in this compilation unit
template class std::shared_ptr<SomeWidelyUsedClass>;

还有:

// SomeOtherFile.cpp
#include "stdafx.h"
#include "SomeWidelyUsedClass.h"

void foo()
{
   // I expect that SomeOtherFile.obj will not include an instantiation of
   // std::shared_ptr<SomeWidelyUsedClass> since it was declared extern in stdafx.h
   std::shared_ptr<SomeWidelyUsedClass>(new SomeWidelyUsedClass());
}

【问题讨论】:

标签: c++ templates visual-c++ visual-studio-2012 explicit-specialization


【解决方案1】:

标准在 §14.7.2/10 中说:

除了内联函数和类模板特化,显式实例化声明具有 抑制它们引用的实体的隐式实例化的效果。

我刚刚签入了 VS2013,std::shared_ptr&lt;&gt; 的实现有一个内联构造函数。这可能是您的extern template 被忽略的原因。

【讨论】:

  • 我相信就是这样。此外,我刚刚被引导到 MS 文档中的这个注释:“特化中的 extern 关键字仅适用于在类主体之外定义的成员函数。在类声明中定义的函数被认为是内联函数,并且总是被实例化。”
  • 实验证实了这一点。对于我在问题中提到的玩具模板类,如果我在类主体之外定义函数,extern template 有效。如果我在其中定义它们,它不会。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-02
  • 2021-08-13
  • 1970-01-01
  • 1970-01-01
  • 2017-07-04
  • 1970-01-01
  • 2017-03-13
相关资源
最近更新 更多