PDA

View Full Version : C++ template class linking issue




GeeYouEye
Feb 13, 2006, 10:55 AM
Hopefully someone can figure out what's going on... I sure can't...

in main.cpp:

#include <iostream>
#include <fstream>
#include <string>
#include "symtab.h"
#include "OpCode.h"
using namespace std;
int main(int argc, char **argv)
{
...
}


in OpCode.h:

#ifndef OPCODE_H
#define OPCODE_H
#include <string>

using namespace std;
class OpCode
{
public:
OpCode(string mnem);
OpCode(string mnem, char hex, int bytes, string otherInfo);
string getMnem() { return iMnem;}
char getHex() {return iHex;}
int getBytes() {return length;}
string getOtherInfo() {return info;}
private:
string iMnem;
char iHex;
int length;
string info;
};
#endif

in OpCode.cpp

OpCode::OpCode(string mnem){iMnem = mnem;}
OpCode::OpCode(string mnem, char hex, int bytes, string otherInfo)
{
iMnem = mnem;
iHex = hex;
length = bytes;
info = otherInfo;
}

Note that all the other functions in OpCode are defined inline.

in symtab.h (where I suspect I'm missing something):
#ifndef SYMTAB_H
#define SYMTAB_H

#include <string>
using namespace std;
template <class AT>
class Item {
public:
Item(string s);
string getname(); // returns the name
AT attr; // attributes other than name
private:
string name;
};

template <class AT>
struct Node{
Item<AT> * info;
Node<AT> * link;};

template <class AT>
class SymTab {
public:
SymTab(); //initializes to the empty table
Item<AT> * find(string s); //returns Item pointer or null
Item<AT> * insert(string s); //inserts if necessary and
//returns Item pointer
~SymTab(); //This seems almost more necessary than the constructor

private:
Node<AT> hashTab[137];
int hash(string s);
Node<AT> * cons(Item<AT> * x, Node<AT> * y); //returns a new list node
// with x in the info field and y in the link field
};

#endif

and in symtab.cpp
#include "symtab.h"
template <class AT>
Item<AT>::Item(string s)
{
name = s;
}
template <class AT>
string Item<AT>::getname() { return name;} // returns the name

template <class AT>
SymTab<AT>::SymTab()
{
}

template <class AT>
Item<AT> * SymTab<AT>::find(string s)
{
...
}

template <class AT>
Item<AT> * SymTab<AT>::insert(string s)
{
...
}

template <class AT>
int SymTab<AT>::hash(string s)
{
...
}

template <class AT>
Node<AT> * SymTab<AT>::cons(Item<AT> *x, Node<AT> * y)
{
Node<AT> * ret = new Node<AT>;
ret->info = x;
ret->link = y;
return ret;
}

template <class AT>
SymTab<AT>::~SymTab()
{
...
}

It compiles fine, but the linker is choking somewhere. Specifically, I get
Undefined symbols:
Item<OpCode>::getname()
SymTab<OpCode>::find(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)
SymTab<OpCode>::insert(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)
SymTab<OpCode>::SymTab()
SymTab<OpCode>::~SymTab()
collect2: ld returned 1 exit status

Everything's defined (although the SymTab constructor doesn't do anything since the only actual data is a fixed array), everything's properly included as far as I can tell... this is driving me nuts. Someone tell me I'm misspelling something somewhere.



zimv20
Feb 13, 2006, 11:38 AM
been a while since i've done this stuff, but...

are you calling the linker properly? it looks like it doesn't know about OpCode.o and symtab.o.

also, from the coding sign, i guess i'm a little suprised that you have template classes that don't have constructors taking AT as an argument.

iSee
Feb 13, 2006, 12:40 PM
All template function definitions need to be in in the header file, either with the class delcaration or inlined after the class declaration.

That is, everything in symtab.cpp needs to be put in symtab.h, either embedded in the class declaration or inline'd afterwards.

Why? In order for a template class to be instantiated for a particular type, ALL the code needs to be available to the compiler. At their heart, templates are automated copy, seatch and replace engines. When you use SymTab<OpCode>, the compiler basically copies everything to do with SymTab from the header file and replaces AT with OpCode and then compiles it. It doesn't have access to the code in symtab.cpp, because that isn't included.

SamMiller0
Feb 13, 2006, 12:40 PM
Please post a tarball of your code and a makefile, I would like to take a look at it.

zimv20
Feb 13, 2006, 12:56 PM
All template function definitions need to be in in the header file
ahh, yeah, that's it. i forgot about that.

GeeYouEye
Feb 15, 2006, 04:40 AM
Yep, it was a combination of splitting it into two files (one bit of C++ I'd forgotten) and the templated constructor issue. Now to just get the rest of this code working...

GeeYouEye
Feb 15, 2006, 05:14 AM
And on that note, I'm trying to read in a hex value from a file. currently, I'm using ifstream infile; infile.open("file.txt"); infile >> hex >> myChar; and the 18 is only being read as 1, with the 8 being parsed later and leading to all sorts of screwups.

Dang how I wish I could just use the Foundation framework.