I'm trying to update some legacy code and I'm running into an interesting problem. I have a static member variable that is defined as a global in a .cpp file. I have a few classes and a struct that are being used in a function (one class is the one with the static member variable). Upon compiling I get a linker error about an undefined symbol (the static member variable,
KeepKeys
).
Error:
1 2 3 4 5 6
|
Undefined first referenced
symbol in file
Element<SiteNode*>::KeepKeys ./ContactSiteList.o
ld: fatal: Symbol referencing errors. No output written to SiteReport
collect2: ld returned 1 exit status
gmake: *** [SiteReport] Error 1
|
Upon further investigation I determined the problem was in a function named
ContactSiteList::UpdateZipCode
. Relevant portion shown here (ContactSiteList.cpp):
1 2 3 4 5 6 7 8 9
|
SiteNode* site = _siteList.GetLastAdded();
// Add the contact and map to site
if( ! _contactList.AddToEnd( _emcSiteOverlay.Extract().Raw(), site ) )
{
// Keys are out of order
errMsg = "EMC_SITE file is not sorted by EMC!";
throw std::runtime_error(errMsg.c_str());
}
|
Where
SiteNode
is a struct (ContactSiteList.h):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
struct SiteNode {
bool Univ18;
bool Univ12;
bool Soho;
bool BizBuyer;
bool HasCompany;
bool FirmAvailable;
Num Contacts;
Num B2BContacts;
Num NoTransContacts;
Num BlankNames; // Number of contacts without contact name
Num BlankCompanies; // Number of contacts without company name
PartNode CategoryHits[ Config::NUM_CATEGORIES ]; // Trans, Dollars, Contacts for each category
// PartCode => PartNode
PartListType PartList;
inline SiteNode() : Univ18(false), Univ12(false), Soho(true), BizBuyer(false),
Contacts(0), B2BContacts(0), NoTransContacts(0),
BlankNames(0), BlankCompanies(0) { }
};
|
...and
_contactList
is a private member function of the
ContactSiteList
class (ContactSiteList.h). Relevant part:
1 2 3 4 5
|
private:
// Maps a partial EMC to a SiteNode
typedef SimpleBinList< SiteNode* > ContactListType;
ContactListType _contactList; // keylength = EMCLIST_EXTRACT_LEN
|
Now, a
SimpleBinList
is a friend class of
Element
, who owns the static member variable
KeepKeys
. Relevant parts shown (SimpleBinList.h):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
template<class T>
class Element {
// For access to Set()
friend class SimpleBinList<T>;
.
.
.
private:
.
.
.
static bool KeepKeys;
};
template<class T>
class SimpleBinList
{
.
.
.
public:
typedef Element<T> ElementType;
.
.
.
private:
void Sort()
{
ElementType::KeepKeys = true;
sort( _theList, _theList + _elementCount, ElementType::SortCompare );
ElementType::KeepKeys = false;
}
.
.
.
};
|
Now, we can find
KeepKeys
globally defined in a .cpp file (SimpleBinList.cpp):
1 2
|
template<class T>
bool Element<T>::KeepKeys = false;
|
SimpleBinList
uses
ElementType::KeepKeys
in several private member functions (one of which is shown above) but none of which are used by
_contactList
in
ContactSiteList::UpdateZipCode
.
Ok, so does anyone have any suggestions to what the problem is and how I can go about fixing it?