Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

does adding a value at the end to a c++ enum defined in an header force recompilation?

Tags:

c++

enums

Background

There is a complex system with several libraries and applications in it, pretty much every project depends upon an header file (foo.h for example) that defines an enum (#included in the several cpp files). The design is far to be ideal (but as usual it is a legacy system).

Sadly, foo.h changes pretty often.

Prerequisite

Let's say that we can guarantee that foo.h will be updated: only adding element at the end, without removing existing values nor redefining them.

Questions

Does such modification requires recompilation of all the code that includes the header? I am aware that this is a common problem with classes (typically removing an unused variable changes the memory layout and cause eventually a core dump). I suspect that can be a similar situation with enums as well, and in normal situation I will surely recompile everything anyway. The current situation introduce a rigidity in all code base that hugely affects the way of the system is evolving.

I would like to know if I "have to" recompile. This information can be used to device the refactoring strategy.

NOTE

I have looked at this question, but I don't think it is actually answering mine.

like image 537
Alessandro Teruzzi Avatar asked Jun 01 '16 13:06

Alessandro Teruzzi


People also ask

Do enums go in header files?

Your code (e.g. your enum) SHOULD be placed in the . h file if you need to expose it to the code you're including the . h file. However if the enum is only specific to the code in your header's .

Can we add constants to enum without breaking existing code?

4) Adding new constants on Enum in Java is easy and you can add new constants without breaking the existing code.

Can you increment an enum?

Incrementing an enumeration requires a cast to convert the integer result of addition back to the enumeration type, as in: d = day(d + 1);

Can enum be defined inside a class C++?

Although enumerations are probably the most common type that is nested inside a class, C++ will let you define other types within a class, such as typedefs, type aliases, and even other classes!


1 Answers

The default answer is: if the contents of your translation unit (= preprocessed source file) changes, you have to recompile it to keep its object file in sync with its source form.

A change in a header file which is #included results in a change in the preprocessed source of the translation unit, so it has to be recompiled to be fully in sync. So from this point of view, a change in the header requires a recompilation.


However, that is the most conservative approach. (And if anything goes wrong with any trickier approach, you should fall back to it). In practice, you may not need to recompile if all you did was add an enumerator to an enumeration.

If you introduce a new enumerator e42 into the header but do not actually use it anywhere in file x.cpp, it's very likely that the object file produced from x.cpp with e42 defined will be 100% identical to the object file produced from x.cpp without e42 defined. So from this point of view, the recompilation is pointless. Ideally, you'd only want to recompile the source file if the generated object file will differ from the pre-change one.

Assuming you do not use the new enumerator in the file, then pretty much the only thing that can force an object file change is this: the size of the enumeration type can change. If your largest enumerator value is 2147483647, and you add a new one, it's quite possible that the size of the enumeration itself will jump from 32 bits to 64 bits.

You can get around this limitation by using C++11's ability to explicitly specify the underlying type of an enumeration. Make sure you specify it for the enumeration which you're extending like that.

enum EnumerationBeingExtended : int
//                            ^^^^^ this part
{
  // ... list of enumerators as before
};

If you have enumeration size (actually entire underlying type) fixed like that, it's very likely that the object files which only contain the old definition of the enumeration (the one without e42) will work just fine with object files containing the new one (the one with e42).

Of course, you will technically be in ill-formed program territory, because the program will violate the One Definition Rule (different translation units have a different definition of that enumeration). However, if all you do is use the enumeration values, you will likely be perfectly safe in practice.

I would be wary of this trick if you do funky stuff like using typeid on the enumeration type. But if you're only using the enumerators and the enumeration type itself "normally," you should be good.

Of course, you should ideally isolate this enumeration to a header file containing only that, and document its intended use heavily. You will also probably have to actually make allowances in your buildsystem for not rebuilding the file because of that header's change.

In summary: formally, you'll have an ill-formed program. But in practice, you should be safe.

like image 196
Angew is no longer proud of SO Avatar answered Oct 13 '22 10:10

Angew is no longer proud of SO