Reputation: 2886
1.cc
struct foo{
const static int bar = 5;
};
int main(){
return foo::bar;
}
2.cc
struct foo{
const static int bar = 6;
};
g++ 1.cc 2.cc
doesn't give a link error.
Does this go against the one definition rule and cause undefined behaviour?
Additionally i'm not sure why const int foo::bar;
was not even needed as suggested by this article: https://www.ibm.com/docs/en/zos/2.1.0?topic=members-static-data
which says:
Note that the constant initializer is not a definition. You still need to define the static member in an enclosing namespace.
But mine compiles with or without it.
Upvotes: 2
Views: 115
Reputation: 40891
You are breaking the One Definition Rule: Class definitions in multiple translation units have to be the same. This makes your program ill-formed, but compiler's don't have to warn you about it.
If you had multiple definitions (const int foo::bar;
), you would probably run into a linker error. But without any definitions, it is difficult for the compiler to detect this at link time, so it just isn't.
In practice, if you had a definition in 1.cc
, you would find that usages in 1.cc
would always evaluate to 5, and in 2.cc
they would sometimes be 6
(always 6
in constant expressions) and sometimes be 5
.
The reason you don't need a definition to have return foo::bar;
is that this does not ODR-use foo::bar
, it is simply a constant expression that evaluates to 5
(without needing a definition of foo::bar
). If you instead had something like:
int copy(const int& x) {
return x;
}
int main() {
return copy(foo::bar);
}
Binding the reference const int& x
would ODR-use foo::bar
, and the linker would complain about there not being a definition for foo::bar
.
Upvotes: 3