-1

So this part of the code is a small part of a large project. I can't copy the entire project but it's really just 2 lines making the error. I'm trying to access the function "mergeSort" from the class Metrics. Metrics is a different class than the one I'm trying to access it in. I've defined mergeSort and also #included Metrics in the class I'm working with. I've also defined the constructor. Here is the piece of code:

void Document::createHashWords()
{
    Node* heads[97];

    string* allWords = parseWords();
    int numWords = getdWordCt();

    for ( int i = 0; i < numWords; i++ )
    {
        char* word = (char*)allWords[i].c_str();
        int k = hashWord(word,97);
        insertWord(heads,k,allWords[i]);
    }

    for ( int i = 0; i < 97; i++ )
    {
        Node* temp = heads[i];
        int size = 0;

        while (temp != NULL)
        {
            size++;
            temp = temp->getNext();
        }

        int* countArr = new int[size];
        temp = heads[i];

        for ( int i = 0; i < size; i++ )
        {
            countArr[i] = temp->getCount();
            temp = temp->getNext();
        }

        Metrics <int> toSort;
        toSort.mergeSort(countArr,size);

    }
}

the Code that is causing the problem is the last 2: Metrics toSort and toSort.mergeSort(countArr,size);.

Here is the Metrics class:

template <class T>
class Metrics
{
private:
    int id;
public:
    Metrics();
    ~Metrics();
    void selectionSort(T *arr, int n);
    void insertionSort(T *arr, int n);
    void merge(T *a, int numA, T *b, int numB, T *c);
    void mergeSort(T *arr, int n);
};

I've defined mergeSort in the .cpp file for that class.

Here is my build error:

1>Document.obj : error LNK2019: unresolved external symbol "public: __thiscall Metrics<int>::Metrics<int>(void)" (??0?$Metrics@H@@QAE@XZ) referenced in function "public: void __thiscall Document::createHashWords(void)" (?createHashWords@Document@@QAEXXZ)
1>Document.obj : error LNK2019: unresolved external symbol "public: __thiscall Metrics<int>::~Metrics<int>(void)" (??1?$Metrics@H@@QAE@XZ) referenced in function "public: void __thiscall Document::createHashWords(void)" (?createHashWords@Document@@QAEXXZ)
1>Document.obj : error LNK2019: unresolved external symbol "public: void __thiscall Metrics<int>::mergeSort(int *,int)" (?mergeSort@?$Metrics@H@@QAEXPAHH@Z) referenced in function "public: void __thiscall Document::createHashWords(void)" (?createHashWords@Document@@QAEXXZ)
1>C:\Users\Kevin\Documents\Visual Studio 2012\Projects\CMPSC 122 Checkpoint 2\Debug\CMPSC 122 Checkpoint 1.exe : fatal error LNK1120: 3 unresolved externals

If I remove those 2 lines, I can compile fine. I just don't know why those 2 lines are wrong. I need to access that function from the Metrics class.

    template <class T>
    class Metrics
    {
    private:
        int id;
    public:
        Metrics<T>() {}
        ~Metrics<T>() {}
        void selectionSort(T *arr, int n);
        void insertionSort(T *arr, int n);
        void merge(T *a, int numA, T *b, int numB, T *c);
        void mergeSort(T *arr, int n);
    };

So this is now my Metrics class:

    template <class T>
    class Metrics
    {
    private:
        int id;
    public:
        Metrics() {}
        ~Metrics() {}
        void selectionSort(T *arr, int n);
        void insertionSort(T *arr, int n);
        void merge(T *a, int numA, T *b, int numB, T *c);
        void mergeSort(T *arr, int n);
    };

I commented out the definitions of the constructor/destructor in the Metrics.cpp file like so:

    //template <class T>
    //Metrics<T>::Metrics()
    //{
    //}

    //template <class T>
    //Metrics<T>::~Metrics()
    //{

    //}

And now this is my error code:

1>Document.obj : error LNK2019: unresolved external symbol "public: void __thiscall Metrics::mergeSort(int *,int)" (?mergeSort@?$Metrics@H@@QAEXPAHH@Z) referenced in function "public: void __thiscall Document::createHashWords(void)" (?createHashWords@Document@@QAEXXZ) 1>C:\Users\Kevin\Documents\Visual Studio 2012\Projects\CMPSC 122 Checkpoint 2\Debug\CMPSC 122 Checkpoint 1.exe : fatal error LNK1120: 1 unresolved externals

  • You don't need `` in the class. So just `Metrics() {}`, etc. – kec Apr 30 '14 at 00:56
  • I did that as well just now. I added what my current metrics class is – user3421510 Apr 30 '14 at 01:01
  • And now your errors are different. You probably have the same issue with the other functions. – kec Apr 30 '14 at 01:02
  • "I've defined mergeSort in the .cpp file for that class." That's your problem. Template functions need to be defined in the header file. [What is an undefined reference/unresolved external symbol error and how do I fix it?: Template implementations not visible](http://stackoverflow.com/a/12574417/902497). – Raymond Chen Apr 30 '14 at 21:30

2 Answers2

0

The missing symbol seems to be the default ctor for Metrics, the one that takes no arguments. Have you defined it? You need to get it included somehow in the same translation unit. The usual way would be to define it in the header file:

template <typename T>
Metrics<T>::Metrics() {}
kec
  • 2,099
  • 11
  • 17
0

Template functions need to be defined in every translation unit (.cpp) they're used in, so you want all of Metrics' member functions to be defined in Metrics.h, as if they were all inlined.

They work differently from normal functions because the code generated is different for every different type used for T, so the compiler can't know what versions to generate when compiling Metrics.cpp.

etheranger
  • 1,233
  • 7
  • 17