Reputation: 1384
I have a weird behaviour with static integal constants:
#include <iostream>
#include <inttypes.h>
class Test{
public:
static const uint32_t Magic = 0x1123;
};
class DataStream{
public:
template<typename T>
DataStream& operator <<( const T& value )
{
std::cout << value << std::endl;
return *this;
}
};
int main()
{
DataStream s;
uint32_t a = Test::Magic; // ok
bool compare = ( a == Test::Magic ); // ok
s << compare;
s << a;
s << Test::Magic; // fail
return 0;
}
I know that such constants should be defined outside of class in .cpp as
const uint32_t Test::Magic;
But strange things is that code above work fine with out line s << Test::Magic;
and produce error only if Magic
used with template operator <<
directly.
Even more error undefined reference to 'Test::Magic'
appear with GCC
, but not with MSVC
.
The question is why I should define Test::Magic
outside of class (even without value!!!), and why my code work fine in some conditions even without such definition?
Upvotes: 4
Views: 1288
Reputation: 75853
§ 9.4.2 Static data members [class.static.data]
If a non-volatile const static data member is of integral or enumeration type, its declaration in the class definition can specify a brace-or-equal-initializer [...] The member shall still be defined in a namespace scope if it is odr-used (3.2) in the program and the namespace scope definition shall not contain an initializer.
[ Note: There shall be exactly one definition of a static data member that is odr-used (3.2) in a program; no diagnostic is required. —end note ]
Upvotes: 1
Reputation: 62603
As a rule, all static const names should be defined in .cpp file if they are ODR used. Taking a reference to the argument is ODR using
them. However, having violated this rule is undefined behavior, and MSVC not reporting an error is just one of the ways undefined behavior can be manifested.
As a practical consideration, you are likely to have the error when function is not inlined, and probably won't see it for the inlined functions. My guess is that inlining works differently with the level of optimization you are using for those compilers.
Upvotes: 2