Для наглядности буду в вопросах использовать следующий класс my_type_1 с конкретизацией его только int'ом. Предполагаем, что small_func маленькая и мы её хотим сделать подставляемой, а big_func большая сложная функция и хотелось бы её реализацию "спрятать".
// my_type_1.h
template<class T>
class my_type_1
{
public:
void small_func() { /*...*/ }
void big_func() { /*...*/ }
};
1. Правильно ли я понимаю, что при использовании шаблонов, совмещающих объявление и определение (как в примере выше), в результирующем исполняемом файле мы получаем столько экземпляров функций my_type_1<int>::big_func, в скольких cpp-файлах она используется (т.е. по одному экземпляру на каждую единицу трансляции)? Зависит ли ответ от компилятора?
2. Правильно ли я понимаю, что если мы сделаем так (см. ниже), то в результирующем исполняемом файле гарантированно всегда будет только один экземпляр my_type_2<int>::big_func, в случае поддержки extern template компилятором? Уменьшится ли время компиляции по сравнению с первым вариантом (с учетом того, что функций типа big_func может быть довольно много)?
// my_type_2.h
template<class T>
class my_type_2
{
public:
void small_func() { /*...*/ }
void big_func() { /*...*/ }
};
// my_type_2_int.h
// Подключается для использования my_type_2<int>
#include "my_type_2.h"
extern template void my_type_2<int>::big_func();
// my_type_2_int.cpp
#include "my_type_2.h"
template void my_type_2<int>::big_func();
3. Уменьшится ли время компиляции второго варианта, если мы его модифицируем так:
// my_type_3.h
template<class T>
class my_type_3
{
public:
void small_func() { /*..*/ }
void big_func();
};
// my_type_3_impl.h
#include "my_type_3.h"
template<class T>
void my_type_3<T>::big_func() { /*..*/ }
// my_type_3_int.h
// Подключается для использования my_type_3<int>
// Компилятор не видит жирное тело big_func в "клиентских" единицах трансляции.
#include "my_type_3.h"
extern template void my_type_2<int>::big_func();
// my_type_3_int.cpp
#include "my_type_3.h"
#include "my_type_3_impl.h" // Определение жирных функций
template void my_type_3<int>::big_func(); // Реализация жирных функций