Does the value add to the end the C ++ enum defined in recompiling the strength of the header?

Background

It has a complex system with several libraries and applications, almost every project depends on the header file (for example, foo.h), which defines the enumeration (#include in several cpp files). The design is far from ideal (but, as usual, it is an outdated system).

Unfortunately, foo.h changes a lot.

Prerequisite

Let's say that we can guarantee that foo.h will be updated: only adding an element at the end, without deleting existing values ​​and without overriding them.

Questions

Is such a modification required to recompile all the code that includes the header? I know that this is a common problem with classes (usually deleting an unused variable changes the memory location and ultimately leads to a core dump). I suspect that this could be a similar situation with transfers, and in a normal situation, of course, I will recompile everything. The current situation creates rigidity in the entire code base, which greatly affects the way the system is developed.

I would like to know if I need to “recompile”. This information can be used to set up a refactoring strategy.

Note

I considered this question , but I do not think that it really answers my question.

+7
c ++ enums
source share
2 answers

Default answer: if the contents of your translation unit (= pre-processed source file) changes, you need to recompile it in order to save its object file in accordance with its original form.

Changing the header file with #include d changes the pre-processed source of the translation unit, so it must be recompiled to be fully synchronized. Therefore, from this point of view, changing the header requires recompilation.


However, this is the most conservative approach. (And if something goes wrong with any more complex approach, you should return to it). In practice, you may not need to recompile if all you have done is add an enumeration to an enumeration.

If you enter a new e42 header in the header but don't actually use it anywhere in the x.cpp file, it is very likely that the object file created from x.cpp with x.cpp will be 100% of the object created from x.cpp without x.cpp . Therefore, from this point of view, recompilation is meaningless. Ideally, you only need to recompile the source file if the generated object file differs from the previously modified one.

Assuming that you are not using a new enumerator in a file, to a large extent the only thing that can lead to a change in the object file is this: the size of the enumeration type can change. If your largest enumerator value is 2147483647, and you add a new one, it is possible that the size of the enumeration itself will go from 32 bits to 64 bits.

You can get around this limitation by using the C ++ 11 feature to explicitly specify the underlying type of an enumeration. Be sure to include it for the listing you are distributing like this.

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

If you have an enumeration size (virtually the entire base type) fixed in this way, it is very likely that object files containing only the old enumeration definition (without e42 ) will work fine with object files containing the new one (one with e42 ).

Of course, you will technically find yourself in a poorly formed territory of the program, because the program will violate the rule of uniform clarity (different units of translation have a different definition for this enumeration). However, if everything you do uses enumeration values, you are likely to be completely safe in practice.

I would be wary of this trick if you make funky, for example, using typeid in an enumeration type. But if you use only enumerations and the enumeration type itself is “normal”, you should be good.

Of course, you should ideally isolate this enumeration with a header file containing just that, and document its intended use to a large extent. You may also have to make allowances on your build system so as not to rebuild the file due to a header change.

In short: formally, you will have a poorly formed program. But in practice, you should be safe.

+4
source share

If the task is to avoid as many recompilations as possible when changing the contents of the enumeration, there is a way that might work for you.

Forward the declaration.

In foo.h:

 enum class MyEnums : int; 

In foo2.h (in fact, I don’t know which file name would be suitable for calling this file, but all that it will contain is the following):

 enum class MyEnums : int { Apple, Orange, Banana, }; 

Usually, you do not need to define your ever-changing enumerations in header files. Only two times do I see this happening when you include implementation details in the header or when you enter default values. If this is the first, now is the time to move these implementations to their .cpp file (unless they are templates ...). This way, usually only your .cpp files will include foo2 to get the definitions sequentially, and the header files that need it will get a numbered enumeration.

This will force you to recompile any cpp files containing foo2, but any header files that include foo will not recompile as a result. And if they do not need to be recompiled, then what includes them does not need to be recompiled. And if they do not need to be recompiled, then what includes them does not need to be recompiled, etc. Etc.

Usually, slow build time in a large code base occurs because someone changed the header, which had a ripple effect in other headers. Only forced recompilation of the cpp file is an easier touch.

You, by the way, are right. Adding a value to an enumeration may cause it to take up another space. Therefore, a forward sentence, as I suggest, requires ": int" or any other similar data type that you need (char, unsigned short, etc.), since this ensures that it will always occupy the same space , which requires passing it to a function; knowledge of space will take, not content.

+1
source share

All Articles