Don't undestand this compiler error

C:\Users\Owner\AppData\Local\Temp\build2075849323474743225.tmp/LED.cpp:75: undefined reference to CArray<CVirtualLED>::~CArray()' LED.cpp.o: In function CClockDisplay':
C:\Users\Owner\AppData\Local\Temp\build2075849323474743225.tmp/LED.cpp:69: undefined reference to `CArray::CArray()'

#ifndef _ARRAY_H
#define _ARRAY_H

#define NULL 0;

template<class T>
class CArrayElement
{
  public:
    // Construction
    CArrayElement();
    ~CArrayElement();
    
    // Implementation
    T m_Element, *m_pNext;
    
};




template<class T>
class CArray
{
  public:
    // Construction
    CArray();
    ~CArray();
    
    // Attributes
    void add(T &rT);
    bool addAt(T &rT, const int nIndex);
    T &operator[](const int nIndex);
    bool deleteAt(const int nIndex);

 protected:
    // Implementation
    CArrayElement<T> *m_pHead;
    CArrayElement<T> m_Blank;
    int m_nSize;
    
};

#endif
#include "Array.h"

template<class T>
CArrayElement<T>::CArrayElement()
{
  m_pNext = NULL;
}

template<class T>
CArrayElement<T>::~CArrayElement()
{
  m_pNext = NULL;
}




template<class T>
CArray<T>::CArray()
{
    m_pHead = NULL;
    m_nSize = 0;
}

template<class T>
CArray<T>::~CArray()
{
  CArrayElement<T> *pCurrent = m_pHead;
  
  while (m_pHead)
  {
    pCurrent = m_pHead->m_pNext;
    delete m_pHead;
    m_pHead = pCurrent;
  }
}

template<class T>
void CArray<T>::add(T &rT)
{
  CArrayElement<T> *pCurrent = m_pHead;
  
  while (pCurrent->m_pNext)
    pCurrent = pCurrent->m_pNext;
  pCurrent->m_pNext = new CArrayElement<T>;
  pCurrent->m_Element = rT;
  m_nSize++;
}

template<class T>
bool CArray<T>::addAt(T &rT, const int nIndex)
{
  CArrayElement<T> *pCurrent = NULL;
  CArrayElement<T> *pPrevious = NULL;
  CArrayElement<T> *pNew = NULL;
  bool bResult = false;
  int nI = 0;
  
  if ((nIndex >= 1) && (nIndex <= m_nSize))
  {
    bResult = true;
    for (nI = 1, pCurrent = m_pHead; nI < nIndex; nI++)
    {  
      pPrevious = pCurrent;
      pCurrent = pCurrent->m_pNext;
    }
    m_nSize++;
    pNew = new CArrayElement<T>;
    pNew->m_Element = rT;
    pNew->m_pNext = pCurrent;
    if (pCurrent == m_pHead)
      m_pHead = pNew;
    else
       pPrevious->m_pNext = pNew;
  }
  return bResult;
}

template<class T>
T &CArray<T>::operator[](const int nIndex)
{
  CArrayElement<T> *pCurrent = NULL;
  int nI = 0;
  T &rResult = m_Blank;

  if ((nIndex >= 1) && (nIndex <= m_nSize))
  {
    for (nI = 1, pCurrent = m_pHead; nI < nIndex; nI++)
    {
      pCurrent = pCurrent->m_pNext;
    }
    rResult  = pCurrent->m_pElement;
  }
  return rResult;
}

template<class T>
bool CArray<T>::deleteAt(const int nIndex)
{
  CArrayElement<T> *pCurrent = NULL;
  CArrayElement<T> *pPrevious = NULL;
  bool bResult = false;
  int nI = 0;
  
  if ((nIndex >= 1) && (nIndex <= m_nSize))
  {
    bResult = true;
    for (nI = 1, pCurrent = m_pHead; nI < nIndex; nI++)
    {  
      pPrevious = pCurrent;
      pCurrent = pCurrent->m_pNext;
    }
    if (pCurrent == m_pHead)
      m_pHead = pCurrent->m_pNext;
    else
       pPrevious->m_pNext = pCurrent->m_pNext;
    delete pCurrent;
    pCurrent = NULL;
  }
  return bResult;
}
#ifndef _LED_H
#define _LED_H

#include "Array.h"

#define BLACK 0
#define RED 1
#define YELLOW 2
#define GREEN 3
#define CYAN 4
#define BLUE 5
#define PINK 6
#define WHITE 7

class CVirtualLED
{
  public:
    // Construction
    CVirtualLED();
    CVirtualLED(const int nRadius, const int nAngle, const int nColor);
    ~CVirtualLED();
    
    // Attributes
    void setPos(const int nRadius, const int nAngle);
    void setRadius(const int nRadius);
    void setAngle(const int nAngle);
    int getAngle();
    int getRadius();
    void setColor(const int nColor);
    int getColor();

  protected:
    // Implementation
    int m_nRadius, m_nAngle, m_nColor;
    
};

[b]typedef CArray<CVirtualLED> CVirtualLEDArray;[/b]

class CClockDisplay
{
  public:
    // Construction
    CClockDisplay();
    ~CClockDisplay();
    
    // Attributes
    void addVirtualLED(CVirtualLED &rVirtualLED);
    int getCircumAt(const int nRadius);
    float Sine(const int nAbgleDeg);
    float Cosine(const int nAbgleDeg);
    void setup();

  protected:
    // Implementation
     [b]CVirtualLEDArray m_arrayClockFace;
[/b]     static const float m_fPi;
     static const int m_nNumRadialLEDs, m_nLEDDiameter, m_nMajClkDiv, m_nMinClkDiv,  m_nLEDRadialSpacing,  m_nLEDCircumSpacing;
};

#endif
#define NULL 0;

Get rid of the semicolon.

Pete

el_supremo:

#define NULL 0;

Get rid of the semicolon.

Pete

Thanks. But it does not solve the undefined reference compiler error.

Removed the semicolon but get the same error;

Not what I get (after removing the obvious b tags)

cplusplus.ino: In destructor ‘CArray::~CArray() [with T = CVirtualLED]’:
cplusplus.ino:226: instantiated from here
cplusplus:72: error: cannot convert ‘CVirtualLED*’ to ‘CArrayElement*’ in assignment

which refers to this line:

    pCurrent = m_pHead->m_pNext;

I just concatenated all the code together for a quick test.

MarkT:
Not what I get (after removing the obvious b tags)

cplusplus.ino: In destructor ‘CArray::~CArray() [with T = CVirtualLED]’:
cplusplus.ino:226: instantiated from here
cplusplus:72: error: cannot convert ‘CVirtualLED*’ to ‘CArrayElement*’ in assignment

which refers to this line:

    pCurrent = m_pHead->m_pNext;

I just concatenated all the code together for a quick test.

Does the arduino IDE have an equivalent of VisualC++ CTRL G (go to line number)?

I simplified the code as follows but still get the same error.

I did away with class CArrayElement and just put the m_pNext in class CVirtualLED

#ifndef _ARRAY_H
#define _ARRAY_H

#define NULL 0

/***************************/
/* CArray                  */
/***************************/

template<class T>
class CArray
{
  public:
    // Construction
    CArray();
    ~CArray();
    
    // Attributes
    void add(T &rT);
    bool addAt(T &rT, const int nIndex);
    T &operator[](const int nIndex);
    bool deleteAt(const int nIndex);

 protected:
    // Implementation
    T *m_pHead;
    T m_Blank;
    int m_nSize;
    
};

#endif
#include "Array.h"

/***************************/
/* CArray                  */
/***************************/

template<class T>
CArray<T>::CArray()
{
    m_pHead = NULL;
    m_nSize = 0;
}

template<class T>
CArray<T>::~CArray()
{
  T *pCurrent = m_pHead;
  
  while (m_pHead)
  {
    pCurrent = m_pHead->m_pNext;
    delete m_pHead;
    m_pHead = pCurrent;
  }
}

template<class T>
void CArray<T>::add(T &rT)
{
  T *pCurrent = m_pHead;
  
  while (pCurrent->m_pNext)
    pCurrent = pCurrent->m_pNext;
  pCurrent->m_pNext = new T;
  *pCurrent = rT;
  m_nSize++;
}

template<class T>
bool CArray<T>::addAt(T &rT, const int nIndex)
{
  T *pCurrent = NULL, *pPrevious = NULL, *pNew = NULL;
  bool bResult = false;
  int nI = 0;
  
  if ((nIndex >= 1) && (nIndex <= m_nSize))
  {
    bResult = true;
    for (nI = 1, pCurrent = m_pHead; nI < nIndex; nI++)
    {  
      pPrevious = pCurrent;
      pCurrent = pCurrent->m_pNext;
    }
    m_nSize++;
    pNew = new T;
    *pNew = rT;
    pNew->m_pNext = pCurrent;
    if (pCurrent == m_pHead)
      m_pHead = pNew;
    else
       pPrevious->m_pNext = pNew;
  }
  return bResult;
}

template<class T>
T &CArray<T>::operator[](const int nIndex)
{
  T *pCurrent = NULL;
  int nI = 0;
  T &rResult = m_Blank;

  if ((nIndex >= 1) && (nIndex <= m_nSize))
  {
    for (nI = 1, pCurrent = m_pHead; nI < nIndex; nI++)
    {
      pCurrent = pCurrent->m_pNext;
    }
    rResult  = *pCurrent;
  }
  return rResult;
}

template<class T>
bool CArray<T>::deleteAt(const int nIndex)
{
  T *pCurrent = NULL, *pPrevious = NULL;
  bool bResult = false;
  int nI = 0;
  
  if ((nIndex >= 1) && (nIndex <= m_nSize))
  {
    bResult = true;
    for (nI = 1, pCurrent = m_pHead; nI < nIndex; nI++)
    {  
      pPrevious = pCurrent;
      pCurrent = pCurrent->m_pNext;
    }
    if (pCurrent == m_pHead)
      m_pHead = pCurrent->m_pNext;
    else
       pPrevious->m_pNext = pCurrent->m_pNext;
    delete pCurrent;
    pCurrent = NULL;
  }
  return bResult;
}
#ifndef _LED_H
#define _LED_H

#include "Array.h"

#define BLACK 0
#define RED 1
#define YELLOW 2
#define GREEN 3
#define CYAN 4
#define BLUE 5
#define PINK 6
#define WHITE 7

/***************************/
/* CVirtualLED             */
/***************************/

class CVirtualLED
{
  public:
    // Construction
    CVirtualLED();
    CVirtualLED(const int nRadius, const int nAngle, const int nColor);
    ~CVirtualLED();
    
    // Attributes
    void setPos(const int nRadius, const int nAngle);
    void setRadius(const int nRadius);
    void setAngle(const int nAngle);
    int getAngle();
    int getRadius();
    void setColor(const int nColor);
    int getColor();

  protected:
    // Implementation
    int m_nRadius, m_nAngle, m_nColor;
    CVirtualLED *m_pNext;
    
};

/***************************/
/* CClockDisplay           */
/***************************/

typedef CArray<CVirtualLED> CVirtualLEDArray;

class CClockDisplay
{
  public:
    // Construction
    CClockDisplay();
    ~CClockDisplay();
    
    // Attributes
    void addVirtualLED(CVirtualLED &rVirtualLED);
    int getCircumAt(const int nRadius);
    float Sine(const int nAbgleDeg);
    float Cosine(const int nAbgleDeg);
    void setup();

  protected:
    // Implementation
     CVirtualLEDArray m_arrayClockFace;
     static const float m_fPi;
     static const int m_nNumRadialLEDs, m_nLEDDiameter, m_nMajClkDiv, m_nMinClkDiv,  m_nLEDRadialSpacing,  m_nLEDCircumSpacing;
};

#endif
// LED.cpp : implementation file
//

#include "LED.h"
#include <arduino.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

/***************************/
/* CVirtualLED             */
/***************************/

CVirtualLED::CVirtualLED()
{ 
  m_nRadius = m_nAngle = m_nColor = 0;
}

CVirtualLED::CVirtualLED(const int nRadius, const int nAngle, const int nColor)
{
  m_nRadius = nRadius;
  m_nAngle = nAngle;
  m_nColor = nColor;
  m_pNext = NULL;
}

CVirtualLED::~CVirtualLED()
{
}

void CVirtualLED::setPos(const int nRadius, const int nAngle)
{
    m_nRadius = nRadius;
    m_nAngle = nAngle;
}

void CVirtualLED::setRadius(const int nRadius)
{
    m_nRadius = nRadius;
}

void CVirtualLED::setAngle(const int nAngle)
{
    m_nAngle = nAngle;
}

int CVirtualLED::getAngle()
{
  return m_nAngle;
}

int CVirtualLED::getRadius()
{
  return m_nRadius;
}

void CVirtualLED::setColor(const int nColor)
{
  m_nColor = nColor;
}

int CVirtualLED::getColor()
{
  return m_nColor;
}




/***************************/
/* CClockDisplay           */
/***************************/

CClockDisplay::CClockDisplay()
{
}

CClockDisplay::~CClockDisplay()
{
}
    
const float CClockDisplay::m_fPi = 3.1416;

const int CClockDisplay::m_nNumRadialLEDs = 25;

const int CClockDisplay::m_nLEDDiameter = 4 /* mm */;

const int CClockDisplay::m_nLEDRadialSpacing = 5 /* mm */;

const int CClockDisplay::m_nMajClkDiv = (int)((float)360 / 12 /* x 5 second blocks */);

const int CClockDisplay::m_nMinClkDiv = (int)((float)360 / 60 /* x seconds */);

const int CClockDisplay::m_nLEDCircumSpacing = 1 /* degree */;

float CClockDisplay::Sine(const int nAbgleDeg)
{
  return sin(nAbgleDeg * (m_fPi / 180));
}

float CClockDisplay::Cosine(const int nAbgleDeg)
{
  return cos(nAbgleDeg * (m_fPi / 180));
}

int CClockDisplay::getCircumAt(const int nRadius)
{
  return (int)(m_fPi * 2 * nRadius);
}

void CClockDisplay::addVirtualLED(CVirtualLED &rVirtualLED)
{
  m_arrayClockFace.add(rVirtualLED);
}

void CClockDisplay::setup()
{
  int nR = 0, nC = 0, nCircum = 0, nNumLEDsAtRadius = 0, nAngle = 0, nRadius = 0;
  CVirtualLED vitualLED;
  const int  nLEDCircumSpacing = (int)((float)m_nLEDDiameter / (float)4);
  
  for (nR = 0; nR < m_nNumRadialLEDs; nR++)
  {
    if (nR == 0)
    {
      vitualLED.setPos(0, 0);
      vitualLED.setColor(WHITE);
    }
    else
    {
      nCircum = getCircumAt(nR * m_nLEDDiameter);
      nNumLEDsAtRadius = (int)((float)nCircum / (float)nLEDCircumSpacing);
      for (nC = 0; nC < nNumLEDsAtRadius; nC++)
      {
        nRadius = nR * m_nLEDRadialSpacing;
        nAngle = (int)(atan2((float)nRadius, (float)nLEDCircumSpacing) * (180.0 / m_fPi)) * 2;
        vitualLED.setPos(nRadius, nAngle);
        vitualLED.setColor(BLACK);
      }
    }
  }         
}

The compiler error seems to be referring to these lines of code:

CClockDisplay::CClockDisplay()
{
}

CClockDisplay::~CClockDisplay()
{
}

But I am still none the wiser as to how to fix it.

May be it would be easier to f off the template classes and just use fixed classes.

CArray<T>::CArray()

The constructor name needs to match the class name.

If I were you, I'd get this working without templates, first.

Found a solution to this compile error.

Apparently with arduino ide, template classes have to be entirely implemented in the header file, otherwise the linker can't 'see' template class functions if they are implemented in the .cpp file.

Did you ever solve this problem? I've just had an expected unqualified-id before error and traced the problem to my definition of a constant PINK. Changed it to pink and all's well!
I don't know why.