开发者

C++ compile error on Visual Studio 10

I'm getting the following error while compiling this simple program using Visual Studio:

error LNK2019: unresolved external symbol "public: void __thiscall CoList<int>::enqueue(int)" (?enqueue@?$CoList@H@@QAEXH@Z) referenced in function _main

error LNK2019: unresolved external symbol "public: virtual __thiscall CoList<int>::~CoList<int>(void)" (??1?$CoList@H@@UAE@XZ) referenced in function _main

error LNK2019: unresolved external symbol "public: int __thiscall CoList<int>::dequeue(void)" (?dequeue@?$CoList@H@@QAEHXZ) referenced in function _main

error LNK2019: unresolved external symbol "public: int __thiscall CoList<int>::count(void)" (?count@?$CoList@H@@QAEHXZ) referenced in function _main

error LNK2019: unresolved external symbol "public: __thiscall CoList<int>::CoList<int>(void)" (??0?$CoList@H@@QAE@XZ) referenced in function _main

error LNK1120: 5 unresolved externals

My program is very simple. I don't use external libraries, just the 'iostream' and 'except开发者_Python百科ion' headers... Here is the full code:

CoList.h

#pragma once

#include "CoListItem.h"

template <class T>
class CoList
{

public:

    CoList();
    virtual ~CoList();

    void enqueue(T value);
    T dequeue();
    T *peek();
    int count();

private:
    CoListItem<T> *m_root;
    int m_count;

};

CoListItem.h

#pragma once

template <class T>
class CoListItem
{

public:

    CoListItem();
    virtual ~CoListItem();

    T value;
    CoListItem *next;

};

CoList.cpp

#include "CoList.h"
#include <exception>

template <class T>
CoList<T>::CoList()
{
}

template <class T>
CoList<T>::~CoList()
{
}

template <class T>
void CoList<T>::enqueue(T value)
{
    if (this->m_root != NULL) {
        this->m_root = new CoListItem<T>();
        this->m_root->value = value;
        this->m_root->next = NULL;
    } else {
        CoListItem<T> *tempitem = new CoListItem<T>();
        tempitem->value = value;
        tempitem->next = this->m_root;

        this->m_root = tempitem;
    }

    this->m_count++;
}

template <class T>
T CoList<T>::dequeue()
{
    if (this->m_root == NULL) {
        throw std::exception();
    } else {
        T retval = this->m_root->value;
        CoListItem *next = this->m_root->next;
        delete this->m_root;
        this->m_root = next;

        return retval;
    }
}

template <class T>
T *CoList<T>::peek()
{
    if (this->m_root == NULL) {
        return NULL;
    } else {
        return *this->dequeue();
    }
}

template <class T>
int CoList<T>::count()
{
    return this->m_count;
}

CoListItem.cpp

#include "CoListItem.h"

template <class T>
CoListItem<T>::CoListItem()
{
}


template <class T>
CoListItem<T>::~CoListItem()
{
}

and finally the main function:

#include <iostream>
#include "CoList.h"
#include "CoListItem.h"

using namespace std;

int main(int argc, char *argv[])
{
    CoList<int> list;

    for(int i = 0; i < 10; i++)
        list.enqueue(i);

    cout << "Count: " << list.count() << endl;

    for(int i = 0; i < 10; i++)
        cout << "Item: " << list.dequeue() << endl;

    cout << "Count: " << list.count() << endl;

    int wait = 0;
    cin >> wait;
}

As you can see it is a very simple Queue implementation using a linked list...


The definitions of function templates(including member functions of class templates) must be in the .h file so that they are present in every cpp file in which they are used. That's how templates work. You cant put the definitions into a cpp file. Technically, there is an export keyword which enables this but since almost no implementation supported it it was removed in the new standard.

Read this: The inclusion model


template definitions should be visible to the code which is using it. For that,

  1. Put all the definitions in ".h" file
  2. Put the definitions in ".cpp" file (for the code separation) and #include that ".cpp" file

For example, in your case you can #include "CoList.cpp" instead of "CoList.h". And so on.


Consider a template function that takes T and performs modulus (%), or a simple addition (+) for that matter.

template <class T>
T GetT(T t1, T t2)
{
    return t1%t2;
}

You see NO ERROR in this code. Alright. When I pass two ints it gets compiled:

GetT(10,20);

But when I pass float/double it WONT compile:

GetT(10.6, 20.5);

Compiler will emit: error C2296: '%' : illegal, left operand has type 'double' and other related errors. The point is that template code doesn't get compiled until you instantiate it at least once for a particular data type. The template code stays junk - compiler doesn't care what actually inside the code. In your case the CPP is nothing but a text-file the compiler has ignored - All of it.

Having said that, when I use operator +, instead of operator % it would work for all basic data-types, but not for classes that are missing operator +. In that case compiler will compile again the template-stuff for that data-type (the class).

There are cases where compiler and linker work together to reduce final binary code size, when they see some code is duplicate and would be same for all/several data-types. But that's a different case.


This is straight from Nicolai Josutis's legendary book,

C++ Templates: A complete Guide

Templates are compiled twice:

  • Without instantiation, the template itself is checked for correct syntax, Syntax errors such as semicolon are discovered here.
  • As the time of instantiation, the templates code is checked to ensure that all calls are valid. Invalid calls are discovered such as unsupported function calls.

This leads to an important problem in the handling of templates practice. When a function template is used in a way that it triggers instantiation, a compiler will (at some point) need to see that template definition. This breaks the usual compile and link distinction for functions, when declaration of function is sufficient to compile the its use.


Thus, For a template the declaration and definition should be kept in the same header file so that they are visible in every cpp which uses them.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜