Что касается раздувания кода, я думаю, что виновником гораздо более вероятно будет встроенный , чем шаблоны.
Например:
// foo.h
template <typename T> void foo () { /* some relatively large definition */ }
// b1.cc
#include "foo.h"
void b1 () { foo<int> (); }
// b2.cc
#include "foo.h"
void b2 () { foo<int> (); }
// b3.cc
#include "foo.h"
void b3 () { foo<int> (); }
Компоновщик, скорее всего, объединит все определения 'foo' в одну единицу перевода. Поэтому размер 'foo' не отличается от размера любой другой функции пространства имен.
Если ваш компоновщик не делает этого, то вы можете использовать явное создание экземпляра, чтобы сделать это для вас:
// foo.h
template <typename T> void foo ();
// foo.cc
#include "foo.h"
template <typename T> void foo () { /* some relatively large definition */ }
template void foo<int> (); // Definition of 'foo<int>' only in this TU
// b1.cc
#include "foo.h"
void b1 () { foo<int> (); }
// b2.cc
#include "foo.h"
void b2 () { foo<int> (); }
// b3.cc
#include "foo.h"
void b3 () { foo<int> (); }
Теперь рассмотрим следующее:
// foo.h
inline void foo () { /* some relatively large definition */ }
// b1.cc
#include "foo.h"
void b1 () { foo (); }
// b2.cc
#include "foo.h"
void b2 () { foo (); }
// b3.cc
#include "foo.h"
void b3 () { foo (); }
Если компилятор решит встроить 'foo' для вас, вы получите 3 разных копии 'foo'. В поле зрения нет шаблонов!
РЕДАКТИРОВАТЬ: Из комментария выше от InSciTek Джефф
Используя явные экземпляры для функций, которые, как вы знаете, будут использоваться только, вы также можете гарантировать, что все неиспользуемые функции будут удалены (что может фактически уменьшить размер кода по сравнению со случаем без шаблона):
// a.h
template <typename T>
class A
{
public:
void f1(); // will be called
void f2(); // will be called
void f3(); // is never called
}
// a.cc
#include "a.h"
template <typename T>
void A<T>::f1 () { /* ... */ }
template <typename T>
void A<T>::f2 () { /* ... */ }
template <typename T>
void A<T>::f3 () { /* ... */ }
template void A<int>::f1 ();
template void A<int>::f2 ();
Если ваша цепочка инструментов не будет полностью разорвана, вышеприведенный код будет генерировать код только для 'f1' и 'f2'.