문제

i decided to create a list (for practice reasons so get off my back about reinvening the wheel thanks..)

I got this LNK2019 ERROR and i belive its code specific becus i cant seem to find a way to fix it ( yes i serched here )

I have found that the problom is coused beacous the complier does not recognize the definitions of the methods, but i cant seem to find out whay. I am using MVS 2010 so the link args are done automatically. here is my code.

List H:

#ifndef _DLIST
#define _DLIST

#include "Node.h"

template<class DataO>
class Dlist
{
private:
    /* Data Members */
             Node<DataO>* _ndHead;
             Node<DataO>* _ndTail;
    unsigned int   _nLength;

    /* Methods */
    void Delete();

public:
    /* Ctors && Dtors */
    Dlist();
    ~Dlist();

    /* Getters && Setters */
    int Length();

    /* Methods */
    void Add(DataO doData);
    void Clear();
    void RemoveAt(unsigned int nIndex);
    void Remove();
};

#endif

List Cpp:

// Dlist.cpp

#include "Dlist.h"

/* ------------------ Dlist Section ------------------ */
/* --- Constracturs && Destractur --- */
template<class DataO> 
Dlist<DataO> :: Dlist()
{
    // Init data
    this->_ndHead = NULL;
    this->_ndTail = NULL;
    this->_nLength = 0;
}

template<class DataO> 
Dlist<DataO> :: ~Dlist()
{
    // Check if we have nodes to delete
    if (this->_nLength > 0);
    {
        this->Clear();
    }
}

/* --- Methods -- */
template<class DataO> 
int Dlist<DataO> :: Length()
{
    // Return the length
    return (this->Length);
}
template<class DataO> 
void Dlist<DataO> :: Add(DataO doData)
{
// Check if head is null
if (this->_ndHead == NULL)
{
    // Create head
    this->_ndHead = new Node<DataO>(doData, NULL, NULL);
}
// Check if tail is null
else if (this->_ndTail == NULL)
{
    // Create tail
    this->_ndTail = new Node<DataO>(doData, NULL, this->_ndHead);

    // Set head's next
    this->_ndHead->SetNext(this->_ndTail);
}
// Create a new Node and replace the tail.
else
{
    // Create a new node.
    this->_ndTail->_ndNext = new Node<DataO>(doData, NULL, this->_ndTail);

    // Make the new node the tail
    this->_ndTail = this->_ndTail->_ndNext;
}
}

Node H:

    template<class DataO> 
class Node
{
private:
    /* Data Members */
    DataO  _doData;
    Node<DataO>*  _ndPrev;
    Node<DataO>*  _ndNext;

    /* Methods */
    void Delete();

public:
    /* Ctors && Dtors */
    Node<DataO>(DataO doData);
    Node<DataO>(DataO doData, const Node& ndNext, const Node& ndPrev);
    ~Node();

    /* Getters && Setters */
    DataO&  GetData();
    void    SetData(DataO doData);

    const Node& GetNext();
          void  SetNext(const Node* ndNextNode);
    const Node& GetPrev();
          void  SetPrev(const Node* ndPrevNode);
};

Node Cpp:

// Node.cpp

#include "Node.h"

/* ------------------ Node Section ------------------ */
/* --- Constracturs --- */
template<class DataO> 
Node<DataO> :: Node(DataO doData)
{
    // Init data
    this->SetData(doData);
    this->SetNext(NULL);
    this->SetPrev(NULL);
}

template<class DataO> 
Node<DataO> :: Node(DataO doData, const Node& ndNext, const Node& ndPrev) 
{
    // Init data
    this->SetData(doData);
    this->SetNext(ndNext);
    this->SetPrev(ndPrev);
}

/*
    -   Node destructor -
    -   Maneges the change of nodes.
    -   Changes the Previous node next node, 
    -   to the current node next node.
*/
template<class DataO> 
Node<DataO> :: ~Node()
{
    // Check that prev is not null
    if (this->GetPrev != NULL)
    {
        // Set prevs Next to current next
        this->GetPrev().SetNext(this->GetNext());
    }
}

/*
    -   GetData -
    -   Returns the data stored in the Node.
*/
template<class DataO> 
DataO& Node<DataO> :: GetData()
{
    // Return the data
    return (this->_doData&);
}

/*
    -   SetData -
    -   Sets the data stored in the Node.
*/
template<class DataO> 
void Node<DataO> :: SetData(DataO doData)
{
    // Sets data
    this->_doData = doData;
}

/*
    -   GetNext -
    -   Returns the next node in the list.
*/
template<class DataO> 
const Node<DataO>& Node<DataO> :: GetNext()
{
    // Returns the next node in the list.
    return (this->_ndNext&);
}

/*
    -   SetNext -
    -   Set the next node in the list.
*/
template<class DataO> 
void Node<DataO> :: SetNext(const Node* ndNextNode)
{
    // Set next node as given node
    this->_ndNext = ndNextNode;
}

/*
    -   GetPrev -
    -   Returns the previous node in the list.
*/
template<class DataO> 
const Node<DataO>& Node<DataO> :: GetPrev()
{
    // Returns the next node in the list.
    return (this->_ndPrev&);
}

/*
    -   SetPrev -
    -   Set the previous node in the list.
*/
template<class DataO> 
void Node<DataO> :: SetPrev(const Node* ndPrevNode)
{
    // Set next node as given node
    this->GetPrev = ndPrevNode;
}
도움이 되었습니까?

해결책

This happens because MSVC compiler does not support extern template. I see your idea, this would be correct approach, but it does not work with most of the compilers. This is because the compiler needs to have access to the entire template definition (not just the signature) in order to generate code for each instantiation of the template. You have 2 options to make it work:

  1. Define all the methods in the header file (like most of the Boost libraries do)

  2. Explicitly instantiate your template class for predefined types (this way your class will not be generic)

See detailed explanation here

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top