0

Better late than never: I am trying to update my code bases to recent C++ standards, right now trying to really understand the intentions of the constexpr syntax feature.

However, I am struggling with this: In one of my microcontroller projects (plain C++ without some of the higher level std features), I have a configuration header that contains a rather large list of #define statements that allow the non-developer user to configure certain constant values (most of the time device-dependant parameters). Example:

#define SERIAL_DEVICE_XY_BAUD_RATE (9600)
#define MAX_SENSORDATA_BUFFER_LENGTH (250)

It seems to me, that this would be a great option to migrate this to constexpr definitions (biggest point for me would be namespaces and type safety for these values).

Now my question: While I want to keep the seperate header file with the configuration constants, how does one use constexpr without duplicating memory allocation? As I understand it, migrating to constexpr like:

constexpr unsigned int device1_baud_rate = 115200;

would give a completely isolated (new) variable with appropriate memory allocated. When using this (like right now with the macro definitions) in the constructor of a class somewhere else in the programm, it gets copied to the member variable, leaving me with two variable allocations instead of one.

I guess I'm missing kind of a concept that makes uses of such constexpr values directly, could anyone point me in the right direction for this usecase? Thanks!

loopend
  • 69
  • 6
  • 2
    These variables do not necessary cause any storage to be allocated unless they are used in the context that explicitly requires so (e.g. pass a pointer to this value to some external function). – user7860670 May 24 '20 at 10:00
  • There is still the enum "hack" to avoid the variable in ODR usage. :/ – Jarod42 May 24 '20 at 10:11

1 Answers1

2

You can always use a tool like godbolt to see what the compiler creates. And if you check the result for this setup you will see that the compiler will generate the same output for #define and costexpr, if you solely use them as constants, even with no optimizations turned on:

#include <iostream>

#define DEFINE_CONST (9600)
constexpr unsigned int constexpr_const = 9600;


int main() {
    int x = DEFINE_CONST;
    int y = constexpr_const;
    std::cout << constexpr_const << std::endl;
    std::cout << DEFINE_CONST << std::endl;
}

Results in:

main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     DWORD PTR [rbp-4], 9600   // int x = DEFINE_CONST;
        mov     DWORD PTR [rbp-8], 9600   // int y = constexpr_const;

        // std::cout << constexpr_const << std::endl;
        mov     esi, 9600 
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >::operator<<(unsigned int)
        mov     esi, OFFSET FLAT:_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
        mov     rdi, rax
        call    std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))

        // std::cout << DEFINE_CONST << std::endl;
        mov     esi, 9600
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
        mov     esi, OFFSET FLAT:_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
        mov     rdi, rax
        call    std::basic_ostream<char, std::char_traits<char> >::operator<<(std::basic_ostream<char, std::char_traits<char> >& (*)(std::basic_ostream<char, std::char_traits<char> >&))
        mov     eax, 0


        leave
        ret
t.niese
  • 39,256
  • 9
  • 74
  • 101
  • Thanks @t.niese as this answered the specific memalloc confusion for the two case as well as point me into the right direction! I'd like to point to [this](https://stackoverflow.com/a/26162710/10192702) answer in a similar question on SO that clarifies the compiler logic regarding storage allocation more in-depth. – loopend May 24 '20 at 11:19