Reputation: 769
Just spent a while debugging a multiple definition error but I'm unclear on why this behavior occurred and would like to understand.
I had something similar to this in a header file.
//foo.h
#pragma once
my_states States[N] = {...};
Later, bar.h
includes foo.h
as bar.cpp
has functions which need to know about my_states
.
The issue arose when I was writing unit tests for bar
and included bar.h
in test.cpp
.
bar.o: multiple definition of MyNamespace::named_states
test.o: first defined here
I have fixed the issue by changing to
constexpr my_states States[n] = {...};
in foo.h
.
However I do not understand why this fixed the issue. I understand I had multiple definitions for the symbol my_states
which confused the linker, but if I have my #pragma once
guard in place, why was this being defined multiple times? I'm unsure why I need the constexpr
qualifier to denote that this should only have 1 definition, when as far as I understand #pragma once
should have prevented the compiler from attempting to create more than 1 definition in the first place.
Upvotes: 0
Views: 934
Reputation: 4713
#pragma once
only ensures that header files are included once only, it doesn't deal with the code.
On your second question regarding my_states
- without constexpr
you attempt to define a global variable that can be modified in runtime (or something like that). By settings its state in the header, you defacto make each library that includes this header file instantiate and contain the variable while it is supposed to be uniquely defined... basically it's a complete mess that cannot compile. You can declare static/global variables in header files but you ought to instantiate them in a single cpp file.
By adding constexpr
to the variable declaration you convey to compiler that it cannot be modified in runtime, and moreover, it's value is known at compile time. So there is no worry about which library stores / instantiates it or anything of the sort since it is an absolute constant known at compile time.
Upvotes: 1