In project development, we usually use conditional compilation to trim code and selectively exclude code that is not needed, for example, if a feature is not supported at all under a certain platform, then that feature should not be compiled.
Generally we use macros to determine the code, selectively pick the parts that need to be compiled, and turn on such conditions in the build system.
Such behavior is normal in C projects, and even in C++ projects, we choose to use macros for conditional judgments.
However, if more macros are defined, it is easy to fragment the code and not visualize the workflow.
For example, code like this:
|
|
As you can see from the above example, once there are a lot of repeated judgment conditions in the code, the code is very unintuitive and split into many parts by macros.
By chance, I saw an article introducing the use of if constexpr in C++ 17, which can perform some calculations during the compilation period. Although I knew about the use of constexpr a long time ago, the examples people gave were basically numerical calculations, allowing the compiler to calculate the values during compilation, thus reducing the runtime consumption, and I never thought of other uses I never thought of other uses for constexpr, so I never used it in my project.
If the code is small and very intuitive, such as the example often given to calculate the Fibonacci sequence during compilation, the compiler will help us open the optimization and give the result directly, even if we don’t use constexpr to explicitly require it.
But if the code is very complex, the compiler may not do this optimization for us, and we need to manually mark where we can compute and ask the compiler to evaluate and optimize during compilation.
What I envision is to use cmake to make a file of the switch values at build time, and then use if constexpr to make conditional judgments where they are needed, and during compilation, the compiler will find a branch that is determined not to be executed (equivalent to if(false) {}
), and then that branch will not be compiled and The branch will not be compiled and will be rejected.
Some work needs to be done in CMakeLists.txt to add the compilation parameters to the build system.
In the options/options.h.in file, import the variables into the file as required by cmake, and replace the contents.
Here I am still using macro definitions, which can also be written directly in the following form.
Write a test code in main.cpp:
The implementation results are as expected.
|
|
Although the result matches, we are actually not sure if the code culling is actually done during compilation, so we use the command to do an assembly to see if the assembly contains a judgment instruction and two output strings.
|
|
main.s
|
|
Looking at the entire main.s assembly, we find that only the expected text string is present in the .L.str segment, and we can conclude that the code was done during compilation to reject it, which meets our requirements.