Рефакторинг кода C ++ для использования форвардных объявлений

У меня довольно обширная кодовая база, и я пытаюсь ее немного привести в порядок, рефакторинг. Одна вещь, которую я хотел бы сделать, - это найти все заголовки, в которые я мог бы пересылать объявленные члены, вместо того, чтобы включать весь файл заголовка.

Это довольно трудоемкий процесс, и я ищу инструмент, который помог бы мне выяснить, в каких заголовках есть элементы, которые можно было бы объявить вперед.

Есть ли параметр компилятора, который может выдавать предупреждение или предположение, что следующий код может использовать предварительное объявление? Я использую следующие компиляторы icc, gcc, sun studio и HP aCC

Есть ли автономный инструмент, который мог бы выполнять ту же работу?

#include "Foo.h"
...//more includes

class Bar {
.......
private:
    Foo* m_foo;
};

person Glen    schedule 19.02.2010    source источник
comment
Было бы неплохо, если бы для этого был разработан инструмент. Если бы он также мог указать все глобальные переменные в моем проекте, я был бы тоже счастлив - они являются основным препятствием для многопоточности в нашей кодовой базе.   -  person Lyndsey Ferguson    schedule 19.02.2010
comment
Будьте осторожны при преобразовании #include в форвардные объявления. Исходные файлы должны иметь #include.   -  person Thomas Matthews    schedule 20.02.2010
comment
@Lyndsey: DMS (см. Мой ответ на этот пост) может легко выбрать ваши глобальные переменные. Его можно настроить для изменения всех обращений к глобальным объектам, для доступа к структуре контекста, содержащей локальные для потока экземпляры этих глобальных объектов.   -  person Ira Baxter    schedule 20.02.2010
comment
Отлично, я добавлю это в закладки и посмотрю. Спасибо.   -  person Lyndsey Ferguson    schedule 20.02.2010
comment
Сработало ли что-нибудь из этого? Это то, чем я хотел бы заниматься и на своей работе.   -  person Setheron    schedule 05.04.2012


Ответы (3)


Все, что связано с точным анализом C ++, требует, по сути, всего внешнего интерфейса C ++ где-то (иначе вы не получите ответов или они будут неправильными, и это плохо работает, когда у вас есть «большие» приложения). Здесь не так много практических ответов.

Уже упоминалось, что GCCXML является производным от GCC пакетом, поэтому он имеет необходимый интерфейс C ++. Он создает XML, поэтому он будет производить БОЛЬШОЙ вывод, который вам нужно будет прочитать, чтобы сформировать «структуру данных в памяти», предложенную в другом ответе. К сожалению, GCCXML уже строит эту структуру данных в памяти, затем экспортирует ее как XML и заставляет вас строить ее заново. Конечно, вы можете просто использовать GCC, который строит структуру данных в памяти, но тогда вам нужно взломать GCC, чтобы он был тем, что вы хотите, и он действительно, действительно хочет быть компилятором. Это означает, что вам придется сражаться за то, чтобы подчинить его своей воле (и объясняет, почему существует GCCXML: большинство людей не хотят этого боя).

Не упоминается интерфейс Edison Design Group C ++ (EDG), который строит его напрямую в структуре данных памяти. Это передняя часть; вам придется делать весь анализ самостоятельно, но ваша задача может быть достаточно простой, так что это не сложно.

Последнее известное мне решение - мое: C ++ FrontEnd для DMS. DMS является основой для построения анализа программ, а его C ++ FrontEnd - это полный интерфейс для C ++ (например, делает все, что делают внешние интерфейсы GCC и Edison: синтаксический анализ, построение дерева, разрешение имени / типа). И вам придется закодировать свой специальный анализ во многом так же, как для GCCXML и EDG, пройдя по структурам данных «в памяти», созданным DMS.

Что действительно отличается, так это то, что DMS можно затем использовать для фактического изменения исходного кода путем обновления тех, которые находятся в структурах данных в памяти, и восстановления компилируемого кода из этих структур памяти, включая исходные комментарии.

person Ira Baxter    schedule 19.02.2010

Я не уверен, что вы найдете что-нибудь, что делает это из коробки, но одним из вариантов было бы написать скрипт с использованием Python и pygccxml, который может провести за вас часть этого анализа.

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

Так, например, вы можете спросить каждый класс, дать мне члены, которые являются типами указателей: тогда для каждого из этих типов указателей вы можете определить, использовался ли реальный экземпляр (не указатель) класса в интерфейсе, а если не вы может пометить его как кандидата на форвардное объявление.

Обратной стороной является то, что для создания сценария потребуется некоторое время, поэтому стоимость может перевесить преимущества, но, по крайней мере, это будет интересное упражнение. Вы можете опубликовать свой код в Github, если у вас есть что-то, что работает, и, возможно, другие сочтут это полезным.

person jkp    schedule 19.02.2010
comment
+1 за упоминание pygccxml: не знал, и это неплохо! - person Francesco; 20.02.2010

Что вы можете сделать, так это вызвать gcc с -MM. Это создаст файлы зависимостей, которые Make может читать. Вместо того, чтобы использовать их, вы можете проанализировать их (с помощью perl или чего-то еще), чтобы определить, какие включения необходимы, а какие можно заменить прямыми объявлениями.

person curlingdude    schedule 19.02.2010
comment
@curlingdude: звучит как интересная идея +1 - person jkp; 20.02.2010