Linker Issue

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?
Last edited on
From what I can tell I can't define Element<T>::KeepKeys as a type T.

In order to fix this problem I had to refactor this code to remove both SimpleBinList and Element and replace them with a Boost ptr_map. Works great now.
Topic archived. No new replies allowed.