// 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' undefined reference to
SomeCls::PERIOD_ALARM_THRESH'
?
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)
If the compiler can't see all the static class constants' values, then you have to provide definitions for them so that they'll actually be stored somewhere. Add the following to your cpp file:
This is a GCC limitation, but it's completely standard comforming. Technically a
static const int
is 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
enum
instead. Or if you're using a new version of GCCconstexpr
was 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 const
for class scope constants. Then I found out that MSVC doesn't allow forstatic const float
with the value inline. So the only values you can portably put in astatic const
are integers, in which caseenum
s provide all the same features plus the guarantee that they'll never silently convert to anlvalue
.If, for whatever reason, you compiler simply refuses to link the code (like GCC 4.4.5 does), here's a simple fix: Replace the
static const int
s with anenum
.This links cleanly with GCC 4.4.5, which wouldn't link the former version, even though both are technically the same.
Note that you cannot, amongst other things, take the address of
PERIOD_ALARM_NORMAL
andPERIOD_ALARM_TRESH
anymore, because both names are just aliases for their respective values.