Влияние использования рекурсивной реализации шаблона для кортежей на время компиляцииC++

Программы на C++. Форум разработчиков
Ответить
Гость
 Влияние использования рекурсивной реализации шаблона для кортежей на время компиляции

Сообщение Гость »


Некоторые источники, например, «Почему нехорошо использовать рекурсивное наследование для реализаций std::tuple?», указывают на затраты времени компиляции при использовании рекурсивной реализации шаблона для кортежей. Я подумываю о написании системы, которая будет использовать сотни кортежей, каждый из которых может иметь размер от 1 до 100 (в среднем от 5 до 10, я думаю), и задаюсь вопросом, стоит ли мне заботиться о том, чтобы стандартные библиотеки, которые я буду использовать, имели рекурсивный подход. выполнение? Может ли кто-нибудь оценить это количественно? влияние на время сборки составляет порядка 25%, или использование памяти примерно на 50% больше? Раньше меня сильно беспокоили другие проблемы с созданием экземпляров шаблонов, поэтому я беспокоюсь.

Мой основной интерес — создание кортежей, а затем их итерация с помощью std::get, вероятно, с использованием кода в следующих строках:

// for_each_tuple: из https://www.cppstories.com/2022/tuple-iteration-apply/ шаблон void for_each_tuple(TupleT&& tp, Fn&& fn) { std::apply([&fn](T&&... args) { (fn(std::forward(args)), ...); }, std::forward(tp)); } std::get явно нерекурсивный, следовательно, O(1) для компилятора, для libstdc++, но код для msvc и gcc не так ясен; Я думаю, что msvc рекурсивен, O (n), но я не могу понять код gcc. Они оба рекурсивные?

msvc имеет std::get

шаблон constexpr tuple_element_t& get(tuple& _Tuple) noException { используя _Ttype = имя типа tuple_element::_Ttype; return static_cast(_Tuple)._Myfirst._Val; } то (в утилите)

шаблон struct tuple_element : tuple_element {}; // рекурсивное определение tuple_element gcc libstdc++

template constexpr __tuple_element_t& get(tuple& __t) noException { return std::__get_helper(__t); } template constexpr _Head& __get_helper(_Tuple_impl& __t) noException { return _Tuple_impl::_M_head(__t); } clang libc++

шаблон имя типа tuple_element::type& get(tuple& __t) _NOEXCEPT { typedef typename tuple_element::type type; return static_cast(__t.__base_).get(); } Две стандартные библиотеки, которые я использую, msvc и gcc, используют рекурсивный подход.

мсвк

шаблон class tuple : Private tuple { // определение рекурсивного кортежа публика: используя _This_type = _This; используя _Mybase = tuple; gcc

/** * Рекурсивная реализация кортежа. Здесь мы храним элемент @c Head. * и получить из @c Tuple_impl, содержащий остальные элементы * (который содержит хвост @c). */ шаблон struct _Tuple_impl : public _Tuple_impl, частная _Head_base { template struct _Tuple_impl; см. лязг

шаблон кортеж класса { typedef __tuple_impl _BaseT; _BaseT __base_; Подводя итог, если я правильно прочитал код стандартной библиотеки, кажется, что по крайней мере один из msvc и gcc std::get является рекурсивным, следовательно, O(n) для компилятора и O (n^2) для кода for_each, который я взял из историй cpp. Можно ли сократить итерацию до O(n) для компилятора? И даже в этом случае требуются ли компилятору значительные затраты времени и пространства из-за рекурсивного характера построения кортежей в msvc и gcc?

(Я использую msvc 2022 17.6, gcc 13.2, clang 16 и удалил некоторые шаблоны из выдержек из стандартных библиотек, чтобы облегчить чтение.)
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»