Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why won't "extern template" work with shared_ptr?

I had the (seemingly) bright idea of using extern template class std::shared_ptr<SomeWidelyUsedClass> in stdafx.h immediately after #include <memory> in order to prevent std::shared_ptr<SomeWidelyUsedClass> from being redundantly instantiated in hundreds of files, figuring I could place template class std::shared_ptr<SomeWidelyUsedClass> in a single .cpp in order to force a single instantiation and hopefully save on compile/link time. However, examination of the resulting .cod and .obj files shows that shared_ptr<SomeWidelyUsedClass> code is being created everywhere anyway. But if I use this exact same technique with my own template class, it works as expected. Is there something special about shared_ptr that precludes this use? Perhaps something in <memory> itself that forces the compiler to create an instantiation before it reaches my extern template statement (I'm very certain there's nothing higher up in stdafx.h that makes use of shared_ptr)?

To clarify:

// 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>;

Then:

// 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>;

And:

// 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());
}
like image 598
dlf Avatar asked May 01 '14 16:05

dlf


People also ask

Why would you choose shared_ptr instead of Unique_ptr?

Use unique_ptr when you want to have single ownership(Exclusive) of the resource. Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another. A shared_ptr is a container for raw pointers.

What is the purpose of the shared_ptr <> template?

std::shared_ptr is a smart pointer that retains shared ownership of an object through a pointer.

What is the difference between shared_ptr and Weak_ptr?

The only difference between weak_ptr and shared_ptr is that the weak_ptr allows the reference counter object to be kept after the actual object was freed. As a result, if you keep a lot of shared_ptr in a std::set the actual objects will occupy a lot of memory if they are big enough.

What happens when shared_ptr goes out of scope?

All the instances point to the same object, and share access to one "control block" that increments and decrements the reference count whenever a new shared_ptr is added, goes out of scope, or is reset. When the reference count reaches zero, the control block deletes the memory resource and itself.


1 Answers

The standard says in §14.7.2/10:

Except for inline functions and class template specializations, explicit instantiation declarations have the effect of suppressing the implicit instantiation of the entity to which they refer.

I just checked in VS2013 and the implementation of std::shared_ptr<> there has an inline constructor. This is probably the reason why your extern template is ignored.

like image 119
jblume Avatar answered Sep 21 '22 08:09

jblume