Concurring with constexpr functions for c++.
As for C for mcu target or sth I personally refrained from struggling with preprocessor to do any advanced crap, found it not really worth the time. I generate initialization lines in included external textfiles with external tools, as those are used for generation od the const data anyway.
Yes, your method has some advantages:
* You increase visibility into the system and remove uncertainty because the exact literal value is available without tediously looking at assembly listing
* You can create a reproducible record of stages that lead into the calculation of the final value. You can do this manually, documented using comments (which, on the other hand, is prone to typing errors, but on the other hand, is error-checkable thanks to visibility), or automated using simple tools - matlab script, python script, a small C program.
One typical example of this mindset difference is; how do you deal with UART baud rate registers? The appealing way is to initialize it like USART->BRR = F_CPU/BAUDRATE, which results in some baud rate you exactly won't know and only trust it "likely works" given some implicit assumptions like F_CPU being many orders of magnitude bigger than BAUDRATE; but the code "looks better" and is more easily modified for different baud rates.
The second way is to manually calculate F_CPU/BAUDRATE, then round it up or down, document the resulting actual baudrate and the error% to the desired baudrate as a comment. The most complex, third option is to write either compile-time tool or runtime configuration function that takes desired baudrate, finds the closest one, makes sure error is below some maximum allowable error threshold, and reports error if it isn't. The first and last options are most error prone due to being simplistic and complex, respectively.