Автоматизируйте рефакторинг #include в C++

У меня есть большой проект с сотнями файлов. И, как это часто бывает с проектами на C++, #includeдирективы путаются. Я хочу реорганизовать их, чтобы повысить ясность, сократить время компиляции и упростить анализ.

Для каждого файла .h я хочу убедиться, что:

  • У него есть #includeдирективы только для типов, которые он использует
  • Но у него есть только предварительные объявления типов, которые используются как T*илиT&

Для каждого файла .cpp я хочу убедиться, что:

  • У него есть #includeдирективы только для типов, которые он использует, и которые еще не включены в другие заголовки (без косвенных включений, когда это возможно)

Я ищу инструмент, который поможет мне автоматизировать этот рефакторинг. На данный момент я знаю только инструменты, которые помогают удалить лишние включения. Некоторые из них:

  • ПК-ворс
  • включить то, что вы используете
  • cppclean
  • ProFactor IncludeManager

Но я не знаю инструментов, которые помогли бы мне переместить необходимые включения в файлы .h или заменить их предварительными объявлениями. Любые идеи? Предпочтительны инструменты для Windows и Visual Studio.

Ответы (1)

Похоже, что include-what-you-use (IWYU) действительно делает то, что я хочу. Хотя это немного сложно использовать в Windows. Но есть даже готовые двоичные файлы Windows , и сопровождающие обещают обновлять их с каждой новой версией clang.

Важным понятием IWYU и его предложений о том, как изменить ваши включения, является «реэкспорт», как указано в документах . По сути, IWYU предлагает напрямую включать файл с объявлением для каждого непосредственно используемого объекта в коде. Или заранее объявить об этом, когда это возможно. Если объект уже не реэкспортирован из других включаемых файлов, т.е. в этом случае его объявление может быть включено косвенно.

Потребовались некоторые усилия, чтобы заставить IWYU работать с файлами из решения Visual Studio 2010, но я получил следующие параметры для include-what-you-use.exe:

include-what-you-use.exe ^
-I "%ProgramFiles(x86)%/Microsoft SDKs/Windows/v7.0A/Include" ^
-I "%ProgramFiles(x86)%/Microsoft Visual Studio 10.0/VC/include" ^
-I "<paths_to_all_your_other_included_dirs>" ^
-DWIN32 -DNDEBUG -D_WINDOWS -D_USRDLL ^
-w -x c++ -std=c++11 -fcxx-exceptions -fexceptions -fms-compatibility -fms-extensions -fmsc-version=1600 -Wno-invalid-token-paste ^
-include stdafx.h ^
-Xiwyu --verbose=2 -Xiwyu --transitive_includes_only ^
you_file.h

Параметры -include stdafx.hнеобходимы при анализе заголовков для предоставления неявно включенных заголовков, таких как std или Qt. На данный момент я протестировал его только на файлах .h, а не на файлах .cpp, но, похоже, он работает довольно хорошо, если вы понимаете, что он на самом деле делает. Вики-страницы действительно полезны.

Надеюсь, это поможет кому-то.

Блестяще, ваша команда сработала сразу
Иногда мне хочется, чтобы я мог проголосовать за ответ более одного раза.