enum в заголовке вызывает чрезмерную перекомпиляцию
Джон Лакос называет эту проблемуковарный источник связи во время компиляции (Рисунок 0-3, в его введении):
Проблема, с которой я сталкиваюсь, заключается в том, что слишком много файлов компилируется, потому что существует физическая зависимость от одного перечисления.
У меня есть заголовок с определением перечисления:
// version.h
enum Version {
v1 = 1,
v2, v3, v4, v5, ... v100
};
и это используется сотнями файлов. Каждый файл определяет класс объектов, которые должны быть прочитаны с диска, используяread()
функция.Version
используется для определения способа чтения данных.
Каждый раз, когда вводится новый класс или член класса, новая запись добавляется в enum
// typeA.cpp
#include "version.h"
void read (FILE *f, ObjectA *p, Version v)
{
read_float(f, &p->x);
read_float(f, &p->y);
if (v >= v100) {
read_float(f, &p->z); // after v100 ObjectA becomes a 3D
}
}
а также
// typeB.cpp
#include "version.h"
void read (FILE *f, ObjectB *p, Version v)
{
read_float (f, &p->mass);
if (v >= v30) {
read_float (f, &p->velocity);
}
if (v >= v50) {
read_color (f, &p->color);
}
}
Теперь, как вы можете видеть, однаждыObjectA
изменения, мы должны ввести новую запись (скажем,v100
) кVersion
, Следовательно, всеtype*.cpp
файлы будут скомпилированы, хотя толькоread()
изObjectA
действительно нужноv100
запись.
Как я могу инвертировать зависимость от перечисления, с минимальными изменениями для клиента (т.е.type*.cpp
), чтобы компилировались только необходимые .c файлы?
Вот возможное решение, о котором я подумал, но мне нужно лучшее:
Я думал, что могу поместить enum в файл .cpp и выставитьint
s со значениями соответствующих членов перечисления:
//version.cpp
enum eVersion {
ev1 = 1,
ev2, ev3, ev4, ev5, ... ev100
};
const int v1 = ev1;
const int v2 = ev2;
....
const int v100 = ev100; // introduce a new global int for every new entry in the enum
сделать псевдоним дляVersion
типа как-то
//version.h
typedef const int Version;
и вводите только значения const int, которые нужны каждый раз:
// typeA.cpp
#include "version.h"
extern Version v100; ///// *** will be resolved at link time
void read (FILE *f, ObjectA *p, Version v)
{
read_float(f, &p->x);
read_float(f, &p->y);
if (v >= v100) {
read_float(f, &p->z); // after v100 ObjectA becomes a 3D
}
}
но я думаю, что это выглядит как очень плохое решение, которое восходит ко времени перед заголовком