// SomeCls.h
class SomeCls
{
static const int PERIOD_ALARM_NORMAL = 5;
static const int PERIOD_ALARM_THRESH = 1;
void method()
{
bool b = true;
const int d = b ? PERIOD_ALARM_THRESH : PERIOD_ALARM_NORMAL;
}
} obj;
It is going to build ok. Now take out the method() implementation and place it in a cpp file:
//SomeCls.cpp
#include "SomeCls.h"
void SomeCls::method()
{
bool b = true;
const int d = b ? PERIOD_ALARM_THRESH : PERIOD_ALARM_NORMAL;
}
Why does mr. linker say
undefined reference to
SomeCls::PERIOD_ALARM_NORMAL' undefinedSomeCls::PERIOD_ALARM_THRESH’
reference to
?
Thanks
EDIT:
It seems to me that that inside .h, the ternary operator takes static const ints it as rvalues but … outside the decalrative .h, it regards them as lvalue and needs definition.
This is what I have managed to understand from the answers below. Kudos to Bada compiler (some eabi linux thinggie)
This is a GCC limitation, but it’s completely standard comforming. Technically a
static const intis still anlvalue. You’ve provided the value inline so compiler will almost always use it as anrvalue. There is one exception. The abstract instructions emitted by the compiler for ternary operators queries the address oflvalues. Hence the error you’re seeing.You can work around this by using
enuminstead. Or if you’re using a new version of GCCconstexprwas added to standard to fix this exact problem (named and typed rvalues).Alternatively you can provide the linker with a definition for the constants. E.g. in your classes cpp file add the a line like
As a side note: I was a staunch proponent of
static constfor class scope constants. Then I found out that MSVC doesn’t allow forstatic const floatwith the value inline. So the only values you can portably put in astatic constare integers, in which caseenums provide all the same features plus the guarantee that they’ll never silently convert to anlvalue.