In C++03 we have template explicit
instantiation definitions (template class
) which force instantiation of a template class.
Foo
In C++11 we've got
template explicit instantiation declarations
(extern template class Foo
) which should prevent
implicit instantiations of a template class. ( href="http://en.cppreference.com/w/cpp/language/class_template" rel="nofollow">Class
template instantiation)
I'm trying to
simulate the situation where I actually needed the explicit instantiation declaration in
order to reduce compilation time. But I can't. Looks like everything works without this
feature (or doesn't work with it).
Here is an
example:
//Foo.h
#pragma
once
template
class
Foo
{
T inst;
public:
Foo(T
i);
T& get()
const;
};
//Foo.cpp
#include
"stdafx.h"
#include "Foo.h"
template T>
Foo::Foo(T inst) : inst(inst) {
}
template
T& Foo::get()
const { return inst; }
template class Foo; //explicit
instantiation
definition
//test1.h
#pragma
once
#include "Foo.h"
//This line does not
work
//extern template class Foo; //explicit instantiation
declaration.
void
baz();
//test1.cpp
#include
"stdafx.h"
#include "test1.h"
void
baz()
{
Foo foo(10);
int i =
foo.get();
}
The
result does not depend on whether I comment
(extern template class Foo
) line or
not.
Here is symbols of both *.obj
files:
dumpbin
/SYMBOLS test1.obj
011 00000000 UNDEF notype
() External | ??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 /SYMBOLS
Foo.obj
017 00000000 SECT4 notype () External
| ??0?$Foo@H@@QAE@H@Z (public: __thiscall Foo::Foo(int))
018 00000000 SECT6 notype () External | ?get@?$Foo@H@@QBEHXZ
(public: int __thiscall Foo::get(void)const
)
Pay attention
what Foo
and int
marked as UNDEF
Foo
in test1.obj which means that they must be resolved elsewhere (i.e. Foo was compiled
only ONCE).
ATTEMP
#2:
If I define full template in Foo.h file
(without explicit instantiation definition) then
extern template
doesn't help - template compiles twice (in both
test1.cpp and
test2.cpp).
Example:
//test1.h
#pragma
once
#include "Foo.h"
void
baz();
//test1.cpp
#include
"stdafx.h"
#include "test1.h"
void baz()
{
Foo foo(10); //implicit instantiation of Foo
int i =
foo.get();
}
//test2.h
#pragma
once
#include "Foo.h"
extern template class
Foo;
void
bar();
//test2.cpp
#include
"stdafx.h"
#include "test2.h"
void
bar()
{
Foo foo(10); //should refer to
Foo from test1.obj but IT IS NOT
int i =
foo.get();
}
Here
are symbol dumps:
dumpbin /SYMBOLS test2.obj
01D 00000000 SECT4 notype () External | ??0?$Foo@H@@QAE@H@Z (public: __thiscall
Foo::Foo(int))
01E 00000000 SECT8 notype ()
External | ?get@?$Foo@H@@QBEHXZ (public: int __thiscall Foo::get(void)const
)
01F 00000000 SECT6 notype () External |
?bar@@YAXXZ (void __cdecl bar(void))
dumpbin
/SYMBOLS test1.obj
01D 00000000 SECT6 notype
() External | ?baz@@YAXXZ (void __cdecl baz(void))
01E 00000000 SECT4 notype () External | ??0?$Foo@H@@QAE@H@Z
(public: __thiscall Foo::Foo(int))
01F
00000000 SECT8 notype () External | ?get@?$Foo@H@@QBEHXZ (public: int __thiscall
Foo::get(void)const
)
In both *.obj
files Foo presents.
So my question is in what
may be the usefulness of the explicit instantiation declarations? Or maybe I miss
something in my tests?
I use VS2013
compiler.
No comments:
Post a Comment