I've also been thinking about this way and I have this question in my mind too. (But I'm noob...)
Another reference: https://msdn.microsoft.com/en-us/library/by56e477.aspx
Maybe explicit extern
is needed?
However, when it's time to link, cpp files has been compiled into .obj
's, but .pch
is not a .obj
...
Then, where will the instantiation of the template functions be? Will the linker be able to read things from the .pch
?
Or we need another separate .cpp
dedicated for instantiating them, while declaring all client references as extern
?
And.. Link-Time Code Generation?
Had some try
It works a little. Testing with VS2012. Turn On compiler profiling and watch the compiler output.
// stdafx.h
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>
#include <vector>
#include <set>
#include <deque>
// stdafx.cpp
#include "stdafx.h"
using namespace std;
template class set<int>;
template set<int>::set();
template set<int>::_Pairib set<int>::insert(const int&);
template class deque<int>;
template deque<int>::deque();
template void deque<int>::push_back(const int&);
template class vector<int>;
template vector<int>::vector();
template void vector<int>::push_back(const int&);
// playcpp.cpp, the entry point
#include "stdafx.h"
using namespace std;
// toggle this block of code
// change a space in the "printf", then build (incrementally)
/*
extern template class set<int>;
extern template set<int>::set();
extern template set<int>::_Pairib set<int>::insert(const int&);
extern template class deque<int>;
extern template deque<int>::deque();
extern template void deque<int>::push_back(const int&);
extern template class vector<int>;
extern template vector<int>::vector();
extern template void vector<int>::push_back(const int&);
*/
int _tmain(int argc, _TCHAR* argv[])
{
set<int> s;
deque<int> q;
vector<int> v;
for(int i=0;i<10000;i++){
int choice=rand()%3;
int value=rand()%100;
switch(choice){
case 0: s.insert(value); break;
case 1: q.push_back(value); break;
case 2: v.push_back(value); break;
}
}
for(const auto &i:s)
printf("%d",i);
for(const auto &i:q)
printf("%d ",i);
for(const auto &i:v)
printf("%d ",i);
return 0;
}
results (lots of others omitted)
with extern declarations:
1> 1630 毫秒 Build 1 次调用
...
1> 757 毫秒 ClCompile 1 次调用
1> 787 毫秒 Link 1 次调用
without extern declarations:
1> 1801 毫秒 Build 1 次调用
...
1> 774 毫秒 Link 1 次调用
1> 955 毫秒 ClCompile 1 次调用
(Chinese version. Legends: 毫秒:ms / milliseconds,x 次调用:x Calls / called x times)
The power settings are adjusted to let the CPU run slow in order to get longer time to avoid turbulence.
Above are just one sample for each case. Still, it's quite unstable. Both cases may sometimes run for ~200ms more.
But trying many times, there's always about 200ms difference on averge. I can just tell that the averages are around 1650ms and 1850ms, with all difference on ClCompile's time.
Of course there are more calls to other template member functions used, just I didn't have the time to figure out all those type signatures... (could anyone tell me which (const) iterator it will use?)
Well but then.... Are there better ways of doing it?