Template class problem

Using my template array in two ways:

  1. With a class CElementDetails object, with a copy constructor.
  2. With a simple int data type

Calling the CArray::add(...) function with my object (class CElementDetails) hangs the sketch up.

Calling the CArray::add(...) function with a simple integer does not hang the sketch up.

What am I missing here with template classes and objects.?

CArray<CElementDetails, 20> m_arrayElementDetails;
CElementDetails E;
m_arrayElementDetails.add(E);

// This hangs up my sketch

And

CArray<int, 20> m_arrayElementDetails;
m_arrayElementDetails.add(10);

// This does nit hang up my sketch

Source file: array.h

template <typename DataType, const uint16_t nMaxSize>
class CArray
{
  public:
    //Construction, destruction & initialisation
    CArray();
    ~CArray();

    bool enqueue(DataType DataVal);
    bool dequeue(DataType &DataVal);
    bool push(DataType DataVal);
    bool pop(DataType &DataVal);
    void fill(DataType DataVal, const uint16_t nSize = 0);
    
    bool add(DataType DataVal);
    bool insertAt(const uint16_t nI, DataType DataVal);
    bool removeAt(const uint16_t nI, DataType &DataVal);
    
    inline bool setAt(const uint16_t nI, DataType DataVal);
    inline bool getAt(const uint16_t nI, DataType &DataVal);
    
    DataType operator [](const uint16_t nI);
    inline uint16_t size();
	  uint16_t capacity();
    inline bool isEmpty();
    void empty();
    bool find(DataType DataVal);

  protected:

    // Data
    DataType m_arrayData[nMaxSize];
    uint16_t m_nCurrSize;
  
};


template <typename DataType, const uint16_t nMaxSize>
CArray<DataType, nMaxSize>::CArray()
{
  memset(m_arrayData, 0, nMaxSize * sizeof(DataType));
  m_nCurrSize = 0;
}

template <typename DataType, const uint16_t nMaxSize>
CArray<DataType, nMaxSize>::~CArray()
{
}

template <typename DataType, const uint16_t nMaxSize>
uint16_t CArray<DataType, nMaxSize>::size()
{
  return m_nCurrSize;
}

template <typename DataType, const uint16_t nMaxSize>
uint16_t CArray<DataType, nMaxSize>::capacity()
{
	return nMaxSize;
}

template <typename DataType, const uint16_t nMaxSize>
bool CArray<DataType, nMaxSize>::isEmpty()
{
  return m_nCurrSize == 0;
}

template <typename DataType, const uint16_t nMaxSize>
void CArray<DataType, nMaxSize>::empty()
{
  m_nCurrSize = 0;
}

template <typename DataType, const uint16_t nMaxSize>
bool CArray<DataType, nMaxSize>::find(DataType DataVal)
{
  bool bResult = false;

  for (uint16_t nI = 0; nI < m_nCurrSize; nI++)
  {
    if (m_arrayData[nI] == DataVal)
    {
      bResult = true;
      break;
    }
  }
  return bResult;
}

template <typename DataType, const uint16_t nMaxSize>
bool CArray<DataType, nMaxSize>::enqueue(DataType DataVal)
{
  return add(DataVal);
}

template <typename DataType, const uint16_t nMaxSize>
bool CArray<DataType, nMaxSize>::dequeue(DataType &DataVal)
{
  return removeAt(m_nCurrSize - 1, DataVal);
}

template <typename DataType, const uint16_t nMaxSize>
bool CArray<DataType, nMaxSize>::push(DataType DataVal)
{
  return insertAt(0, DataVal);
}

template <typename DataType, const uint16_t nMaxSize>
bool CArray<DataType, nMaxSize>::pop(DataType &DataVal)
{
  return removeAt(0, DataVal);
}

template <typename DataType, const uint16_t nMaxSize>
void CArray<DataType, nMaxSize>::fill(DataType DataVal, const uint16_t nSize)
{
  if (nSize > 0)
    m_nCurrSize = nSize;
  else
    m_nCurrSize = nMaxSize;

   memset(m_arrayData, 0, nMaxSize);
}

template <typename DataType, const uint16_t nMaxSize>
bool CArray<DataType, nMaxSize>::add(DataType DataVal)
{
  bool bResult = false;
  
  if (m_nCurrSize < nMaxSize)
  {
    m_arrayData[m_nCurrSize++] = DataVal;
    bResult = true;
  }
  return bResult;
}

template <typename DataType, const uint16_t nMaxSize>
bool CArray<DataType, nMaxSize>::insertAt(const uint16_t nI, DataType DataVal)
{
  bool bResult = false;
  
  if ((nI < m_nCurrSize) && ((m_nCurrSize + 1) == nMaxSize))
  {
    for (uint16_t nJ = m_nCurrSize; nJ > nI; nJ--)
    {
      m_arrayData[nJ] = m_arrayData[nJ - 1];
    }
    m_arrayData[nI] = DataVal;
    m_nCurrSize++;
    bResult = true;
  }
  return bResult;
}

template <typename DataType, const uint16_t nMaxSize>
bool CArray<DataType, nMaxSize>::removeAt(const uint16_t nI, DataType &DataVal)
{
  bool bResult = false;
  
  if (nI < m_nCurrSize)
  {
    DataVal = m_arrayData[nI];
    for (uint16_t nJ = nI; nJ < (m_nCurrSize - 1); nJ++)
    {
      m_arrayData[nJ] = m_arrayData[nJ + 1];
    }
    m_nCurrSize--;
    bResult = true;
  }
  return bResult;
  
}

template <typename DataType, const uint16_t nMaxSize>
bool CArray<DataType, nMaxSize>::setAt(const uint16_t nI, DataType DataVal)
{
  bool bResult = false;
  
  if (nI < m_nCurrSize)
  {
    bResult = true;
    m_arrayData[nI] = DataVal;
  }
  return bResult;
}

template <typename DataType, const uint16_t nMaxSize>
bool CArray<DataType, nMaxSize>::getAt(const uint16_t nI, DataType &DataVal)
{ 
  bool bResult = false;

  if (nI < m_nCurrSize)
  {
    DataVal = m_arrayData[nI];
    bResult = true;
  }
  return bResult;
}

template <typename DataType, const uint16_t nMaxSize>
DataType CArray<DataType, nMaxSize>::operator [](const uint16_t nI)
{
  if (nI < m_nCurrSize)
  {
    return m_arrayData[nI];
  }
  else
  {
    assert(false);
  }
}

Source file: displayelements.h

class CDisplayElements
{
  public:
    CDisplayElements();
    virtual ~CDisplayElements();

    bool begin();
    void dump();
    void doGetNextDisplayElement(CElementDetails &ElementDetails);

  protected:

    const char *m_strDelim;
    CArray<CElementDetails, 20> m_arrayElementDetails;
    uint8_t m_nElementIndex;

    // Helpers
    bool readFile();
    bool readTextElement(CString &strFileLine, CElementDetails &ElementDetails);

};

Source file: displayelements.h

CElementDetails::CElementDetails(): m_strText(m_buffText)
{
    m_nColor = m_nTimeMillis = 0;
    m_nPasses = 1;
    m_nAnimation = 0;
    m_bFlash = false;
}

CElementDetails::CElementDetails(CElementDetails &ElementDetails): m_strText(m_buffText)
{
  (*this) = ElementDetails;
}

CElementDetails::~CElementDetails()
{

}

CElementDetails& CElementDetails::operator =(CElementDetails &ElementDetails)
{
  m_strText = ElementDetails.m_strText.c_str();
  m_nColor = ElementDetails.m_nColor; 
  m_nTimeMillis = ElementDetails.m_nTimeMillis; 
  m_nAnimation = ElementDetails.m_nAnimation; 
  m_bFlash = ElementDetails.m_bFlash;
  m_nPasses = ElementDetails.m_nPasses;

  return *this;
}

void CElementDetails::dump()
{
  LOG(F("============================="));
  DUMP_VAR(m_strText);
  DUMP_VAR(m_nColor); 
  DUMP_VAR(m_nTimeMillis); 
  DUMP_VAR(m_nAnimation); 
  DUMP_VAR(m_bFlash);
  DUMP_VAR(m_nPasses);
  LOG(F("============================="));
}

I'm, not sure, this is just a guess. When calling add (CElementDetails) there are some instances created and some destructed. I would suggest adding debug messages in CElementDetails constructors and destructor to see what is really going on. Taking a brief look at your code:

template <typename DataType, const uint16_t nMaxSize>
bool CArray<DataType, nMaxSize>::add(DataType DataVal) <- A instance constucted as a parameter to call add function
{
  bool bResult = false;
  
  if (m_nCurrSize < nMaxSize)
  {
    m_arrayData[m_nCurrSize++] = DataVal; <- B instance constructed as a copy of parameter instance
    bResult = true;
  }
  return bResult; <- A parameter instance destructed
}



template <typename DataType, const uint16_t nMaxSize>
CArray<DataType, nMaxSize>::~CArray() 
{
<- no B CElementDetails destructor called here, but the memory gets removed ???
}

By the way, is there a reason you are not using std::vector instead?

No, it doesn't. The code you posted doesn't even compile. The datatype CElementDetails is not defined.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.