Бывают случаи, когда я хочу перегружать или специализировать шаблоны, которые уже были вызваны ранее из-за циклических зависимостей.
Поскольку они являются шаблонами, решение обычно состоит в том, чтобы разделить объявление и определение.
Однако, если эти шаблоны должны быть частью #included библиотеки, это означает, что вам нужно два #include:
- Один для декларации , которая должна быть до всех специализаций.
- Один для "позднего" определения , которое должно быть после всех специализаций.
(Удаленное ключевое слово C ++ export (до C ++ 11) было потенциальным решением, но у него было множество проблем).
У кого-нибудь есть какие-либо решения, позволяющие избежать необходимости второго #include?
Я считал:
Попытка создать некую единственную шаблонную функцию пересылки "late_call", которая определена в конце источника и использует некоторый механизм для вывода целевой функции из ее параметров. К сожалению, я вижу только, как это может работать в особых случаях.
- [-] В основном не работает.
- [-] Требует #include в конце источника.
Создание расширяемого списка заголовков для включения через препроцессор с последующим включением их всех в конце через один финальный #include.
Можно взломать такой список с фиксированным количеством мест, используя множество # определений.
- [-] Искусственный предел.
- [-] Использует макрос #include, который испортит некоторые инструменты.
- [-] Гадкий как ад.
- [-] Требуется #include в конце источника.
Создание моей собственной ручной команды прагма-типа, затем написание внешнего инструмента для запуска предварительно обработанного кода и перемещения чего-либо перед компиляцией.
- [+] Отлично работает.
- [+] Ничего не нужно добавлять в конец источника.
- [-] Это в значительной степени гарантирует, что никто никогда не захочет использовать мою библиотеку, и я, вероятно, тоже буду ненавидеть ее.
Создание «late.hpp», в которое я добавляю #include для каждого позднего определения, защищенное #ifdefs, чтобы проверить, нужны ли они.
- [-] Требует #include в конце источника.
- [-] Полностью нарушает модульность.
В конце добавить список заголовков поздних определений вручную.
- [-] Разрывает модульность. Исходные файлы могут косвенно приобретать новые требования позднего определения, если изменяются другие реализации.
- [-] Гадкий.
- [-] Потенциальный источник ошибок.