Предположим, что у меня есть класс, который содержит большое количество других объявлений класса. Возможно ли каким-либо образом расходовать их стоимость таким образом, чтобы потребление памяти во время компиляции не увеличивалось квадратично для вложенных типов? Я готов принять удар по времени компиляции, если это необходимо, и с удовольствием разделил бы это на разные единицы перевода, если бы это был вариант.
Чтобы попытаться найти решение, я написал следующую программу, которая иллюстрирует упрощенную версию кода, которая приводит к этим выбросам:
// Add T to the list of args of SeqWithArgs N number of times:
template <int N, typename T, typename SeqWithArgs>
struct Append;
template <int N, typename T, template <typename...> class Seq, typename... Args>
struct Append<N, T, Seq<Args...>>
{
using type = typename Append<N-1, T, Seq<Args..., T>>::type;
};
template <typename T, template<typename...> class Seq, typename... Args>
struct Append<0, T, Seq<Args...>>
{
using type = Seq<Args...>;
};
static constexpr const int N = 10;
// Tuple containing N instances of int
using Small = typename Append<N, int, std::tuple<>>::type;
// Tuple containing N instances of Small
using Big = typename Append<N, Small, std::tuple<>>::type;
// Tuple containing N instances of Big
using Huge = typename Append<N, Big, std::tuple<>>::type;
int main()
{
Huge h;
return 0;
}
Как уже отмечалось Якком, эти операции Append
ужасно неэффективны. Однако в реальной версии этого кода для их модификации потребуется фундаментальная реструктуризация кода.
Я изменил N
с 10 до 70 и получил этот результат, компилируя мою программу, используя GCC 4.8.1
. Я также запускал time -v make
для получения максимального использования памяти резидентной памяти. Вот результаты, используя только флаги по умолчанию:
Этот результат кажется чрезмерным для меня, а не из-за формы (ожидается, что это O (N ^ 3) и, похоже, следует этой форме), но из-за величины. Похоже, что Small
расширяется для каждого экземпляра Big, а Big в свою очередь расширяется для каждого экземпляра Huge. В менее тяжелом коде кода обычно объявляется общая специализация какого-либо типа с использованием ключевого слова extern
и поэтому избегает этого "вложенного расширения", но это типы, а не значения; что-то подобное существует для такого типа конструкции?
В чем причина этого выброса в памяти и что я могу сделать для уменьшения этого объема памяти без изменения типа Small
, Big
и Huge
?