Предотвращение циклических перегрузок и зависимостей специализации в библиотеке (AKA manual C ++ метод экспорта) - PullRequest
0 голосов
/ 25 июня 2018

Бывают случаи, когда я хочу перегружать или специализировать шаблоны, которые уже были вызваны ранее из-за циклических зависимостей.

Поскольку они являются шаблонами, решение обычно состоит в том, чтобы разделить объявление и определение.

Однако, если эти шаблоны должны быть частью #included библиотеки, это означает, что вам нужно два #include:

  • Один для декларации , которая должна быть до всех специализаций.
  • Один для "позднего" определения , которое должно быть после всех специализаций.

(Удаленное ключевое слово C ++ export (до C ++ 11) было потенциальным решением, но у него было множество проблем).

У кого-нибудь есть какие-либо решения, позволяющие избежать необходимости второго #include?


Я считал:

  1. Попытка создать некую единственную шаблонную функцию пересылки "late_call", которая определена в конце источника и использует некоторый механизм для вывода целевой функции из ее параметров. К сожалению, я вижу только, как это может работать в особых случаях.

    • [-] В основном не работает.
    • [-] Требует #include в конце источника.
  2. Создание расширяемого списка заголовков для включения через препроцессор с последующим включением их всех в конце через один финальный #include. Можно взломать такой список с фиксированным количеством мест, используя множество # определений.

    • [-] Искусственный предел.
    • [-] Использует макрос #include, который испортит некоторые инструменты.
    • [-] Гадкий как ад.
    • [-] Требуется #include в конце источника.
  3. Создание моей собственной ручной команды прагма-типа, затем написание внешнего инструмента для запуска предварительно обработанного кода и перемещения чего-либо перед компиляцией.

    • [+] Отлично работает.
    • [+] Ничего не нужно добавлять в конец источника.
    • [-] Это в значительной степени гарантирует, что никто никогда не захочет использовать мою библиотеку, и я, вероятно, тоже буду ненавидеть ее.
  4. Создание «late.hpp», в которое я добавляю #include для каждого позднего определения, защищенное #ifdefs, чтобы проверить, нужны ли они.

    • [-] Требует #include в конце источника.
    • [-] Полностью нарушает модульность.
  5. В конце добавить список заголовков поздних определений вручную.

    • [-] Разрывает модульность. Исходные файлы могут косвенно приобретать новые требования позднего определения, если изменяются другие реализации.
    • [-] Гадкий.
    • [-] Потенциальный источник ошибок.
...