2

I have this code here:

#ifndef BT_ORDER_HPP
#define BT_ORDER_HPP

class Order {
public:
    /*....*/
private:
    static unsigned long long id_generator;
    const  unsigned long long id;
};

unsigned long long Order::id_generator = 0; 


#endif//BT_ORDER_HPP

it does not compile if the header file is included in multiple compilation units because, as far as I understood, the static variable is defined in all the compilation units. But that does not make sense to me, because I am using ifndef guards; I thought that the compiler would check if the macro was already defined and in that case omit the code that is guarded by the block, definition of the static variable included. This specific class I am making has a lot of inlined, simple functions, so creating a source .cpp file for this would solve the problem, and it's the standard way to go about this, but in this case i feel like it's unnecessary, since I would have to make a whole new file with only two lines of code:

#include "order.hpp"
unsigned long long Order::id_generator = 0;

Can anyone explain what is going on here and offer an elegant solution?

ugo_capeto
  • 129
  • 8
  • 3
    `unsigned long long Order::id_generator = 0;` line should be in exactly one source file. Include guards help avoid duplicate definitions when a header is included more than once in the same source; they have nothing to do with including the same header in multiple sources. – Igor Tandetnik Mar 26 '23 at 15:08
  • 3
    Include guards protect from double inclusion in *the same translation unit*. – StoryTeller - Unslander Monica Mar 26 '23 at 15:08
  • 4
    With a sufficiently modern compiler, you can write `inline static unsigned long long id_generator;` within the class, then you won't need a separate definition outside the class. The search term for further research is "inline variable". – Igor Tandetnik Mar 26 '23 at 15:12
  • @IgorTandetnik so in order to ensure that the line is only in one source file i have to make a dedicated source file with that line in it? – ugo_capeto Mar 26 '23 at 15:16
  • 1
    @ugo_capeto if your compiler supports c++17 you can use `inline static unsigned long long id_generator = 0;` in your class `Order` definition in the h file. No need for a cpp file. See here: https://stackoverflow.com/questions/38043442/how-do-inline-variables-work. – wohlstad Mar 26 '23 at 15:36
  • 1
    @ugo_capeto - I see you've already got a good solution, but I thought I'd mention that your code is most likely _compiling_ okay, but it's at the _linking_ phase that it fails - you successfully create a bunch of *.o files, but when the linker tries to assemble them into a single *.exe, it sees multiple copies of the `Order::id_generator` symbol. Lots of people/toolchains don't distinguish strongly between the two phases, so that might not mean much to you, but it might help you understand what's happening. – JonathanZ Mar 26 '23 at 17:44
  • @JonathanZsupportsMonicaC thanks for the clarification, it's helpful to make that distinction – ugo_capeto Mar 26 '23 at 20:12

0 Answers0