+1
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
#include <iostream>
template<typename T>
struct CrtpBase {
static float base_func()
{
std::cout << "CrtpBase::base_func(), " << typeid(T).name() << "::int_field == "
<< T::int_field << std::endl;
return 16.0f;
}
static inline float x = base_func();
};
struct A: public CrtpBase<A> {
void func_a()
{
base_func();
}
static inline int int_field = 16;
};
struct B : public CrtpBase<B> {
void func_b()
{
std::cout << "B::func_b(), no CrtpBase<B>::base_func() call" << std::endl;
}
};
int main()
{
A a;
a.func_a();
B b;
b.func_b();
}
[temp.inst]/2:
Unless a class template specialization is a declared specialization,
the class template specialization is implicitly instantiated when
the specialization is referenced in a context that requires a
completely-defined object type or when the completeness of the
class type affects the semantics of the program.
[temp.inst]/3:
The implicit instantiation of a class template specialization causes
(3.1) -- the implicit instantiation of the declarations, but not of the definitions, of
the non-deleted class member functions, member classes, scoped member enumerations,
static data members, member templates, and friends; and
(3.2) -- the implicit instantiation of the definitions of deleted member functions,
unscoped member enumerations, and member anonymous unions.
[temp.inst]/4:
Unless a member of a templated class is a declared specialization, the specialization
of the member is implicitly instantiated when the specialization is referenced in a
context that requires the member definition to exist or if the existence of the definition
of the member affects the semantics of the program; in particular, the initialization
(and any associated side effects) of a static data member does not occur unless the
static data member is itself used in a way that requires the definition of the static
data member to exist.
Таким образом, по стандарту CrtpBase<B>::x не должен быть инициализирован, поскольку он нигде не used in a way that requires the definition of the static data member to exist. Правильные компиляторы (gcc и clang) это понимают и компилируют код, а вот Visual Studio зачем-то пытается инициализировать CrtpBase<B>::x и нон-конформно ломается.
Запостил: PolinaAksenova,
24 Марта 2021
KoWe4Ka_l7porpaMMep 24.03.2021 02:57 # +1
PolinaAksenova 24.03.2021 03:55 # +1
bormand 24.03.2021 03:55 # +1
PolinaAksenova 24.03.2021 03:58 # +3
j123123 24.03.2021 05:12 # 0
KoWe4Ka_l7porpaMMep 24.03.2021 06:37 # 0
j123123 24.03.2021 09:43 # 0
bormand 24.03.2021 09:49 # +1
TOPT 24.03.2021 09:49 # +1
Desktop 24.03.2021 11:23 # +1
j123123 24.03.2021 11:39 # 0
guest6 24.03.2021 12:37 # +2
j123123 24.03.2021 12:48 # +1
guest6 24.03.2021 12:59 # +2
А в RAII это из коробки:) Но разумеется не бесплатно, а ценой охулиона всяких интересных "вопросиков"
j123123 24.03.2021 13:50 # 0
А куда он в "RAII" уходит? Он же в каком-то там деструкторе тоже будет.
bormand 24.03.2021 13:51 # 0
MAKAKA 24.03.2021 13:52 # 0
delete_group(&grp);
delete_user(&usr);
Рантайм сам последовательно вызовет деструкторы в порядке, обратном вызову констуркторов.
j123123 24.03.2021 14:00 # +1
Выше по треду там есть ссылка на вариант без гнутого расширения https://govnokod.ru/24517
guest6 24.03.2021 14:14 # 0
PolinaAksenova 24.03.2021 14:26 # 0
А код с гнутыми расширениями — говно по умолчанию, поскольку не соответствует стандарту.
j123123 24.03.2021 14:34 # 0
Почему это? Можно такое и на файловый дескриптор типа int навесить, чтоб вызывалось close() по выходу.
PolinaAksenova 24.03.2021 14:48 # 0
.
j123123 24.03.2021 14:53 # 0
bormand 24.03.2021 14:54 # 0
j123123 24.03.2021 15:00 # 0
bormand 24.03.2021 15:02 # 0
Должен, но он же просто адрес локалки получает в данном случае. Ну вот как-будто бы ты в сишке позвал cleanup_foo(&f) для какой-то структурки, которая у тебя на стеке валяется (а в ней файловый дескриптор).
MAKAKA 24.03.2021 15:07 # 0
так вот жи:
>&f
лол)
Я тоже подумал, что jциферки говорит про вызов деструктора через указатель. А он просто про то, что деструктор должен знать по какому адресу лежит объект, который он собирается уничтожать.
Ну логично
MAKAKA 24.03.2021 14:56 # 0
Указатель обязателен для полиморфизма и вирт методов, ну и для работы с кучей само собой.
А без этого можно вообще про указатели ничего не знать кмк
j123123 24.03.2021 15:05 # 0
Можно написать и с указателями, и компилятор может соптимизировать так, чтобы реально никаких указателей не было.
j123123 24.03.2021 14:37 # 0
Что значит "для каждой новой переменной нужно делать новый блок"?
PolinaAksenova 24.03.2021 14:50 # 0
j123123 24.03.2021 15:07 # 0
bormand 24.03.2021 14:39 # +1
Х.з., я прагматик -- если стандарт не предлагает красивого и простого решения, то можно и конпеляторозависимой магии наифдефать. Главное более-менее инкапсулировать это, чтобы кишки наружу не торчали. В макрос завернуть хотя бы.
Всё лучше, чем городить хрупкий лес из костылей и тонкостей стандарта.
Soul_re@ver 24.03.2021 14:53 # +1
PolinaAksenova 24.03.2021 15:04 # 0
Общение между программами через расшаренную память (которая тоже системозависимая, да ещё и неоднозначно транслирующаяся, чёрт бы побрал эти CreateFileMapping()+MapViewOfFile()) — это какой-то мазохизм, в обычной прикладухе он не нужен (обычная прикладуха спокойно гоняет данные через локальные сокеты… которые тоже до сих пор не стандартизированы).
MAKAKA 24.03.2021 15:06 # 0
Когда-нить и до остального доберутся.
PolinaAksenova 24.03.2021 15:07 # +1
Soul_re@ver 24.03.2021 15:18 # +1
PolinaAksenova 24.03.2021 15:28 # +1
Soul_re@ver 24.03.2021 15:40 # +2
j123123 24.03.2021 14:06 # 0
Что значит "рантайм"? Разве для этого нужен какой-то "рантайм" со стороны крестов? Это можно тупо препроцессором каким-то накостылить, что если переменная выходит из скоупа, то вызываем такую-то хуетень.
bormand 24.03.2021 14:08 # +1
Нет конечно, это ж не джава какая-нибудь... У меня нет никакого рантайма, а RAII работает. Просто конпелятор сам расставляет вызов деструкторов в точках выхода.
Soul_re@ver 24.03.2021 14:58 # +1
The program can't start because vcruntime140.dll is missing from your computer. Try reinstalling the program to fix this problem.
MAKAKA 24.03.2021 14:59 # 0
bormand 24.03.2021 15:20 # 0
Ради экономии это делать глупо, да. Но есть и другие причины, например операционка -- это ты сам. Некому сисколлы кидать.
Soul_re@ver 24.03.2021 15:22 # 0
bormand 24.03.2021 15:46 # 0
Угу, к примеру вызов 16-битного прерывания через 64-битный интерфейс, переданый по шаред поинтеру.
MAKAKA 24.03.2021 16:09 # 0
Кстати, efi через CSM зарботал, спасибо.
Я тут еще вспомнил, что каждая карта должна уметь VGA вообще без всякого VBE, так что сделать универсальный драйвер всё таки можно.
Стандартнаые (не X) режимы позволяют иметь до 640x480 на 16 цветов, а 320x200 даже в 256 (тот самый 13h вроде)
Просто видимо уефи думает, что 320x200 маловато по современным меркам
bormand 24.03.2021 16:20 # 0
Не уверен про современные карты.
А по uefi спеке все машины с ним обязаны поддерживать как минимум 800х600 емнип.
MAKAKA 24.03.2021 18:10 # 0
То есть гоблины первые у меня не заработают в досе?
MAKAKA 24.03.2021 15:23 # 0
Не очень понятно причем тут выпил CRT из винды тогда)
bormand 24.03.2021 15:34 # 0
Compiler-support library?
Unwinder?
Аллокатор?
Обёртки над сисколлами?
Всякие memcpy и strcpy?
Крестолибу?
Какие-то важные части запилены, конечно. Если они имеют смысл для не-hosted окружения.
MAKAKA 24.03.2021 15:36 # 0
Хотя вот например динамическая память может и не иметь смысла для какой-то мелкой пижни где ты -- единственная прогорамма
guest6 24.03.2021 14:10 # 0
ты прав
PolinaAksenova 24.03.2021 14:26 # +1
MAKAKA 24.03.2021 14:28 # +1
TOPT 24.03.2021 14:28 # 0
bormand 24.03.2021 13:15 # 0
MAKAKA 24.03.2021 13:16 # 0
bormand 24.03.2021 13:21 # 0
MAKAKA 24.03.2021 13:24 # 0
bormand 24.03.2021 13:28 # 0
MAKAKA 24.03.2021 13:29 # +2
"Moving to C++ seems wiser than using a dubious hack like this."
j123123 24.03.2021 15:31 # 0
MAKAKA 24.03.2021 15:33 # 0
Хотя вроде бы можно и отказаться от него
PolinaAksenova 24.03.2021 15:34 # 0
MAKAKA 24.03.2021 15:38 # 0
j123123 24.03.2021 15:37 # 0
PolinaAksenova 24.03.2021 15:37 # 0
j123123 24.03.2021 15:39 # 0
Неймспейсы, миксины можно использовать, RAII есть, switch по строкам еще...
MAKAKA 24.03.2021 15:49 # 0
А если "D" настолько охуенен, то почему его никто не использует?
j123123 24.03.2021 15:53 # 0
MAKAKA 24.03.2021 15:57 # +1
Я просто совершенно однозначно могу сказать, что еще один язык с GC точно не нужен. Их и так охулион и маленькая тележка
j123123 24.03.2021 15:38 # 0
MAKAKA 24.03.2021 15:41 # 0
А RTTI большинство крестовиков не использует (хочется думать)
PolinaAksenova 24.03.2021 15:43 # 0
Ну и любой dynamic_cast<> — это уже RTTI так-то.
MAKAKA 24.03.2021 15:47 # 0
PolinaAksenova 24.03.2021 15:51 # 0
MAKAKA 24.03.2021 15:56 # 0
Самому Страуструпу он не очень нравится емнип
Soul_re@ver 24.03.2021 15:47 # 0
PolinaAksenova 24.03.2021 15:48 # 0
j123123 24.03.2021 15:48 # 0
"void *" хватит всем.
PolinaAksenova 24.03.2021 15:52 # 0
j123123 24.03.2021 15:59 # 0
MAKAKA 24.03.2021 16:01 # +2
и тут мы снова возвращаемся к моему любимому
збс
PolinaAksenova 24.03.2021 16:03 # +1
bormand 24.03.2021 16:04 # 0
А type_info оно один раз на класс, не на объект. Так что если сильно не метушить и не создавать тысячи типов, то оно не так уж много занимает. Тем более линкер выбросит лишнее, если ты не юзаешь.
Soul_re@ver 24.03.2021 16:16 # 0
Это std::variant получается. Все типы, что у тебя в программе присутствуют, в 8 бит не запихнёшь. А если всю шаблонометушню посчитать, то и в 16 не факт, что уложишься.
bormand 24.03.2021 16:30 # +1
256 типов хватит для любого сишника.
PolinaAksenova 24.03.2021 16:33 # 0
CHayT 24.03.2021 16:34 # 0
MAKAKA 24.03.2021 16:35 # 0
PolinaAksenova 24.03.2021 16:49 # 0
Не то сына, не то дочь;
Не мышонка, не лягушку,
А неведому крестушку.
guest6 24.03.2021 16:51 # 0
guest6 24.03.2021 17:04 # +2
Или даже так: а вдруг Гост это и есть Полина Аксёнова?
guest6 24.03.2021 17:14 # 0
CHayT 24.03.2021 17:45 # +1
MAKAKA 24.03.2021 16:35 # 0
Soul_re@ver 24.03.2021 16:37 # +1
Soul_re@ver 24.03.2021 16:37 # 0
j123123 24.03.2021 17:28 # 0
Ну так требования к выравненности указателей на разных платформах могут быть раные, и на какой-то платформе если указатель 64-битный но его допустимо выравнивать по 32-битной границе, и свой аналог type_info будем хранить в 32-битах, то массив из такой структуры будет по 32 бита экономить на каждый элемент, в сравнении с двумя обычными указателями
bormand 24.03.2021 17:31 # 0
Ну это странная архитектура какая-то... Требует чтения не меньше 32 бит, но при этом кеша нет и от натурального выравнивания 64 бит на 64 профита нету?
j123123 24.03.2021 17:34 # 0
j123123 24.03.2021 17:32 # 0
и делать связный список из такой фигни
Rooster 24.03.2021 17:36 # +1
MAKAKA 24.03.2021 17:37 # +2
Soul_re@ver 24.03.2021 17:48 # 0
PolinaAksenova 24.03.2021 17:51 # 0
MAKAKA 24.03.2021 17:52 # 0
Rooster 24.03.2021 17:54 # 0
MAKAKA 24.03.2021 17:56 # 0
Интересно решение, кстати:)
PolinaAksenova 24.03.2021 17:58 # 0
j123123 24.03.2021 17:58 # 0
Когда никакого интернета не было, компьютеры занимали большой машинный зал и программировались через перфоленты-перфокарты, ошибкой это не было. Эксплоиты никого не парили, потому что кто-то просто приходит со своей программой, запускает ее, получает распечатку с результатом выполнения и потом уходит.
PolinaAksenova 24.03.2021 18:01 # 0
MAKAKA 24.03.2021 18:02 # 0
bormand 24.03.2021 18:04 # 0
MAKAKA 24.03.2021 18:07 # 0
PolinaAksenova 24.03.2021 18:09 # 0
MAKAKA 24.03.2021 18:10 # +1
PolinaAksenova 24.03.2021 18:12 # +5
guest6 24.03.2021 18:21 # 0
PolinaAksenova 24.03.2021 18:50 # 0
j123123 24.03.2021 19:18 # 0
Они думают что ты - https://govnokod.ru/user/8086
PolinaAksenova 24.03.2021 19:34 # 0
KoWe4Ka_l7porpaMMep 24.03.2021 20:07 # +1
От слов «пони» и «ня»? :з
bootcamp_dropout 24.03.2021 18:52 # 0
Кто ещё использует m dash на говнокоде
gologub 24.03.2021 18:53 # +1
guest6 24.03.2021 21:34 # +1
j123123 24.03.2021 18:10 # 0
bormand 24.03.2021 15:50 # 0
Да, крестолиба к сожалению на них намертво завязана. Ты можешь их не юзать, конечно. Но приходится сразу прощаться с векторами и прочими няшными штуками.
MAKAKA 24.03.2021 15:59 # 0
Джава вся тоже в исключениях
Но уже в .NET стали завозить всякие "TryParse", то есть уже в 1999-м было понятно, что исключения это не всегда хорошо
j123123 24.03.2021 16:01 # +1
MAKAKA 24.03.2021 16:02 # 0
ничего, ща вам микропитон завезут в контроллеры, и будут у вас и исключения, и ооп, и всё, что ты любишь
j123123 24.03.2021 16:12 # 0
Тут есть кое-какие ньюансы. Если исключения реализуются через механизм setjmp/longjmp хуйни, то от рантайма там только эта setjmp/longjmp хуита нужна, а это вообще из сишного рантайма хрень.
А если механизм исключений реализуется через unwind tables какие-то, см
т.е. в бинарнике есть некое говно https://habr.com/ru/post/208006/ :
> Концептуально, на каждый адрес кода программы хранится информация о том, как попасть в вышестоящий фрейм вызова. На практике ввиду объемности этой информации, она сжимается, фактически, вычисляется с помощью интерпретации байт-кода. Этот байт-код исполняется при возникновении исключения. Расположено всё это в секциях ".eh_frame" и ".eh_frame_hdr".
Да, помимо всего прочего, DWARF интерпретатор представляет собой отличный backdoor, с помощью которого, подменив байт-код, можно перехватить исключение и отправить его на обработку куда душе угодно.
Вот это уже серьезный рантайм.
А в винде тоже есть свое говно с какими Thread Information Block, и о нем в той статье на хабре тоже упоминается.
Еще можно какое-то говно через ретурны сделать теоретически, даже setjmp/longjmp не потребуется, но это пиздец будет, после каждого ретурна проверяем хуйню и если хуйня выставлена то тогда опять ретурним... можно какой-то говнопрепроцессор под это сделать. Считать ли такую дрисню рантаймом?
j123123 24.03.2021 16:37 # 0
Тут конечно же надо уточнить, что если надо просто прыгнуть по стекфрейам - это одно дело, а если надо прыгнуть по стекфреймам с вызовом деструкторов для всякого там RAII по дороге - это уже другое. И там уж в стекфрейме надо вспомогательную инфу хранить, типа если бросили исключения, то вот эти деструкторы надо б вызвать по дороге... А что если исключение произойдет в деструкторе когда мы уже обрабатываем исключение? Скорее всего, упадет всё нафиг.
PolinaAksenova 24.03.2021 16:45 # 0
j123123 25.03.2021 07:59 # 0
Ну ок, допустим что есть raii-шная обертка над файловым дескриптором, которая в деструкторе делает close(fd). Но close может завершиться с ошибкой:
Предположим, где-то в коде мы успешно открыли файл, начали с ним что-то делать, и тут срабатывает исключение в какой-то фигне, мы раскручиваем стек, надо вызвать close() для файла, но вызвать close не выходит. Ну проверили мы std::uncaught_exceptions(), ну да, раскручиваем стек, и че? Какие дальнейшие действия?
bormand 25.03.2021 08:00 # 0
А в сишке?
j123123 25.03.2021 08:07 # 0
Или можно сделать exit(EXIT_FAILURE);
Или можно сделать механизм как бы снапшотов через вызовы fork() - ну типа если мы хотим файловый дескриптор открыть, мы перед этим форкаемся, открываем файловый дескриптор в одном из процессов, а в другом самому себе отправляем SIGSTOP и по просыпанию (если оно произойдет) мы типа знаем, что что-то пошло не так. Ну и если где-то какая-то фигня, то тот основной процесс прибивается, и мы продолжаем с того процесса, который до этого спал. И он уже знает что там фигня какая-то, и файл открывать не будет. Но тут всё сложно, ведь если в файловый дескриптор что-то записывалось, то мы эти изменения откатить не сможем т.к. это за пределами нашей компетенции.
bormand 25.03.2021 08:10 # 0
Это как? close() вроде нельзя звать второй раз, ошибка из него неисправима.
Ну т.е. два адекватных варианта остаётся:
- заигнорить (можно и в крестах)
- завершить прогу (кидай исключение, кресты сами завершат)
j123123 25.03.2021 08:14 # 0
Тут всё не так однозначно
https://stackoverflow.com/a/33114363
> In theory, POSIX was unclear in the past as to whether the fd remains open when close fails with EINTR, and systems disagreed. Since it's important to know the state (otherwise you have either fd leaks or double-close bugs which are extremely dangerous in multithreaded programs), the resolution to Austin Group issue #529 specified the behavior strictly for future versions of POSIX, that EINTR means the fd remains open. This is the right behavior consistent with the definition of EINTR elsewhere, but Linux refuses to accept it. (FWIW there's an easy workaround for this that's possible at the libc syscall wrapper level; see glibc PR #14627.) Fortunately it never arises in practice anyway.
> Per the (amended) standard, on EINTR the fd remains open. However, Linux does not honor this and glibc does not work around the failure to honor it. See the links in my answer. Fortunately EINTR does not happen on close on Linux in any real-world situations I'm aware of, anyway.
bormand 25.03.2021 08:15 # 0
Какой багор )))
j123123 25.03.2021 08:17 # 0
bormand 25.03.2021 08:57 # 0
Заебись. Т.е. если я пишу кроссплатформенный код, мне придётся писать ifdef'ы для каждой операционки, которая возвращает ошибку при EINTR? Ну и забивать на утечку дескрипторов для неизвестных мне ОС.
В очередной раз убеждаюсь, что нехуй вообще было мешать запись и закрытие в один сисколл. Лучше бы всегда в успешной ветке флашить чем пердолиться с ошибками от закрытия... Но теперь это говно уже не исправить, походу.
j123123 25.03.2021 09:40 # +1
Именно поэтому я за микроконтроллеры - там этой хуйни вообще нет изначально.
bormand 25.03.2021 09:41 # 0
В каких-нибудь либах от вендоров такого говнеца хватает, я думаю. Но их можно не юзать.
bormand 25.03.2021 09:23 # 0
j123123 25.03.2021 09:41 # 0
Надо еще учесть, что при логгировании может эксепшен сработать.
bormand 25.03.2021 09:47 # 0
Да, но тут лучше весь логгер noexcept'ным сделать раз и навсегда. В сишке ведь тоже никто не обрабатывает ошибки от логирующих макросов.
YpaHeLI_ 25.03.2021 10:51 # 0
Так и надо, никогда не видел, чтобы у логгера были какие-то ошибки.
Проиницализировал и забыл.
j123123 24.03.2021 16:45 # 0
https://habr.com/ru/post/433944/ - да, упадет.
bormand 24.03.2021 16:13 # 0
Да кстати нет... Все вот эти if (err) return err весят не сильно меньше. Успешный путь исключения не портят (в нормальном конпеляторе). Да и по фейлу время вполне детерминированное.
j123123 24.03.2021 16:14 # 0
А если всю программу хуйнуть в одну функцию и скакать по ней через goto?
bormand 24.03.2021 16:17 # +2
Кстати, вот многие сишники плюются от исключений, а сами юзают убогий setjmp.
PolinaAksenova 24.03.2021 16:26 # 0
PolinaAksenova 24.03.2021 16:24 # 0
Но если серьёзно, то похожий подход применяется в sqlite, например: там перед компиляцией все исходники сваливаются в один огромный .c-файл — пишут, что так оптимизация лучше получается на десяток процентов.
MAPTbIwKA 26.03.2021 20:58 # 0
днище-то какое
bormand 24.03.2021 08:32 # 0
Rooster 24.03.2021 10:25 # 0
j123123 26.03.2021 10:35 # 0
bormand 26.03.2021 10:48 # +1
Мемоизация тоже есть (prrecompiled headers), но она вроде только на парсинг, а не на кодогенерецию.
Soul_re@ver 26.03.2021 13:07 # 0
bormand 26.03.2021 13:35 # 0
Помнится, я в студии умудрился внутри функции шаблонов наебашить. А потом удивился, что гцц со шлангом так не умеют.
PolinaAksenova 26.03.2021 18:07 # +1
Причём шаблонные классы, шаблонные функции, методы, полностью определённые в определении класса, constexpr-функции, constexpr-статические члены класса и ещё какие-то сущности объявлены inline по умолчанию, и линкер обязан их чистить вилкой без явных указаний программиста.
bormand 26.03.2021 18:19 # 0
Т.е. у инлайн функции во всех единицах трансляции один адрес? Хм, не задумывался о такой гарантии.
PolinaAksenova 26.03.2021 18:24 # +1
MAPTbIwKA 26.03.2021 19:17 # +1
А всё потому, что код смешали с данными
bormand 26.03.2021 22:02 # 0
При этом невиртуальные функции вообще никак не привязаны к данным после конпеляции.
MAPTbIwKA 26.03.2021 22:05 # 0
j123123 26.03.2021 18:43 # +1
bormand 26.03.2021 18:53 # 0
j123123 26.03.2021 20:52 # 0
Да, это конечно сложно, но зато это будет охуенно легко скейлиться, можно на куче каких-нибудь распберри-пай какую-то говнину так собирать параллельно, облачную питушню всякую подключать можно.
MAPTbIwKA 26.03.2021 20:54 # 0
А так они срут одинаковым говном, которое потом мерджится
j123123 26.03.2021 20:58 # 0
> А так они срут одинаковым говном, которое потом мерджится
Сначала проверяем, есть ли там такое говно, потом делаем и срем в бд если нет, а если есть, то берем его, если надо. Можно ж еще как-то умно распределить, какой компилятор какую хуину будет делать, чтобы не было повторов.
MAPTbIwKA 26.03.2021 21:01 # 0
Хотя в целом конечно идея не компилировать одно и тоже -- хорошая
j123123 26.03.2021 21:02 # 0
Можно коммитить туда, как git какой-нибудь.
bormand 26.03.2021 21:04 # 0
MAPTbIwKA 26.03.2021 21:11 # 0
Раньше это делали вручную или внешней тулой (кажется у pmake есть команда или даже внешняя, makedepend), потом вроде gcc сам научился.
guest6 26.03.2021 14:24 # 0
https://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html