1009 | | 2. Precompiled headers:: todo |
1010 | | |
1011 | | 3. extern template pre-instantiated copies of your templates with their most common template parameters into a separate static library:: todo |
| 1011 | '''2. Precompiled headers''' |
| 1012 | |
| 1013 | You probably noticed that in the table above that precompiled headers gain nothing on clang, +13% on GCC and +70% on MSVC. Those percentages vary according to source code, but I have found them fairly similar across my own projects - on MSVC, precompiled headers are a must have on an already much faster compiler than any of the others. |
| 1014 | |
| 1015 | Turning on precompiled headers in Boost.Build is easy: |
| 1016 | {{{ |
| 1017 | cpp-pch afio_pch : afio_pch.hpp : <include>. ; |
| 1018 | }}} |
| 1019 | And now simply link your program to afio_pch to enable. If you're on cmake, you definitely should check out https://github.com/sakra/cotire. |
| 1020 | |
| 1021 | '''3. `extern template` your templates with their most common template parameters in the headers, and force instantiate those same common instances into a separate static library''' |
| 1022 | |
| 1023 | The following demonstrates the technique: |
| 1024 | {{{#!c++ |
| 1025 | // Header.hpp |
| 1026 | template<class T> struct Foo |
| 1027 | { |
| 1028 | T v; |
| 1029 | inline Foo(T _v); |
| 1030 | }; |
| 1031 | // Definition must be made outside struct Foo for extern template to have effect |
| 1032 | template<class T> inline Foo<T>::Foo(T _v) : v(_v) { } |
| 1033 | |
| 1034 | // Inhibit automatic instantiation of struct Foo for common types |
| 1035 | extern template struct Foo<int>; |
| 1036 | extern template struct Foo<double>; |
| 1037 | |
| 1038 | |
| 1039 | // Source.cpp |
| 1040 | #include "Header.hpp" |
| 1041 | #include <stdio.h> |
| 1042 | |
| 1043 | // Force instantiation of struct Foo with common types. Usually compiled into |
| 1044 | // a separate static library as bundling it into the main shared library can |
| 1045 | // introduce symbol visibility problems, so it's easier and safer to use a static |
| 1046 | // library |
| 1047 | template struct Foo<int>; |
| 1048 | template struct Foo<double>; |
| 1049 | |
| 1050 | int main(void) |
| 1051 | { |
| 1052 | Foo<long> a(5); // Works! |
| 1053 | Foo<int> b(5); // Symbol not found if not force instantiated above |
| 1054 | Foo<double> c(5); // Symbol not found if not force instantiated above |
| 1055 | printf("a=%l, b=%d, c=%lf\n", a.v, b.v, c.v); |
| 1056 | return 0; |
| 1057 | } |
| 1058 | }}} |
| 1059 | The idea behind this is to tell the compiler to not instantiate common instantiations of your template types on demand for every single compiland as you will explicitly instantiate them exactly once elsewhere. This can give quite a bump to build times for template heavy libraries. |