Я выделил различные вопросы и комментарии к "внешним" объявлениям шаблонов и тому, как они могут сократить время компиляции, явно указав компилятору не создавать экземпляр определенного класса шаблона или функции в модуле перевода.
Однако я просто не могу заставить эти внешние объявления работать с GCC 8.1.0.
Пример, который я создал, - это в основном принтер кортежей, который std :: cout все элементы кортежа из 512 элементов. Реализация for_each использует общий вызов функции для каждого элемента, в SO имеется несколько версий.
test.hpp
#include <iostream>
#include <tuple>
#include "for_each.hpp"
constexpr auto t = std::tuple{ 0, ..., 511};
template<typename T>
struct Test {
void print() {
for_each(t, [](auto v) { std::cout << v << "\n"; });
}
};
test.cpp
#include "test.hpp"
template class Test<int>;
Несколько исходных файлов теперь создают экземпляр Test и используют функцию печати.
src0.cpp
#include "test.hpp"
extern template class Test<int>;
void src0() {
Test<int> t;
t.print();
}
Насколько я понимаю, Test и его функция печати теперь должны создаваться только один раз test.cpp, а не src0.cpp или другими исходными файлами с объявлением шаблона как extern. Однако это не то, что происходит. Для каждого исходного файла, который я добавляю, который использует Test , выполняется другая реализация ... Так как GCC имеет тенденцию выделять ОЧЕНЬ много памяти для создания вызовов функций и типов / (лямбда-выражения), это становится очень утомительным и отнимает много времени. Ниже приведено изображение потребления памяти моей машиной при компиляции трех исходных файлов с использованием Test ...
![memory usage](https://i.stack.imgur.com/JclyF.png)
Я что-то здесь упускаю ?? Я подумал, для чего именно «внешний шаблон» должен использоваться?
реализация for_each для завершения:
for_each.hpp
#pragma once
#include <tuple>
namespace detail {
template<typename T, typename F, size_t... Is>
constexpr void for_each_impl(T&& t,
F&& f,
std::integer_sequence<size_t, Is...>) {
(f(std::get<Is>(std::forward<T>(t))), ...);
}
} // namespace detail
template<typename T, typename F>
constexpr void for_each(T&& t, F&& f) {
detail::for_each_impl(std::forward<T>(t),
std::forward<F>(f),
std::make_index_sequence<
std::tuple_size_v<std::remove_reference_t<T>>>{});
}