Pointer, generic class, functions… so much complex for me

Hi,

I’m “objectizing” my code. First, I create a generic Array class. Then I refactor my code unsuccessfully, I re-refactor my code unsuccessfully, I re-re-refactor my code… I’m lost.

My error is:

Core2.cpp:33: error: no matching function for call to 'Schedule::Schedule(int, const prog_char [17], int, int, Array&)’
Schedule.h:40: note: candidates are: Schedule::Schedule(byte, const prog_char
, boolean, unsigned int, Array)
Schedule.h:37: note: Schedule::Schedule(const Schedule&)

An my related files:

#ifndef ARRAY_H_
#define ARRAY_H_
#include <Arduino.h>

template<class T>
class Array {
  public:
  Array(const T* elements);
  __attribute__((always_inline)) inline const T* getElments() { return this->_elements; };
  __attribute__((always_inline)) inline const uint8_t size()  { return this->_size; };
  
  protected:
  const T* _elements;
  uint8_t _size;
};

template <class T> 
Array<T>::Array(const T* elements)
{
  this->_size = ARRAYLEN(elements);
  this->_elements = elements;
}
#endif ARRAY_H_
#ifndef SCHEDULE_H_
#define SCHEDULE_H_
#include <Arduino.h>
#include <avr/pgmspace.h>
#include "macros.h"
#include "Array.h"
#include "Connector.h"

class Schedule : public ConnectorDigital {
  public:
  Schedule(byte id, const prog_char* label, const boolean isNC, unsigned int data, Array<const uint8_t>* digitals) {
    this->_pin      = (id << 2) | isNC;
    this->_label    = label;
    this->_schedule = data;
    this->_digitals = digitals;
  };
  
  protected:
  unsigned int _schedule;
  Array<const uint8_t>* _digitals;
};
#endif SCHEDULE_H_

and Core2.cpp:

static const uint8_t schedulePins_13_values[] = { 1, 2, 3, 4 };
Array<uint8_t>* schedulePins_13 = new Array<uint8_t>(schedulePins_13_values);
static Schedule schedule_13 = Schedule(13, Dictionary::test, false, 1324, schedulePins_13 );

I’m confused :confused:

You are breaking the encapsulation by storing the data outside the class.
Why are you using a template for this, if the result object is inside another class, you need some way of using the template parameter. If not then you don’t really need a template as uint8_t is enforced.

Here is an array template that works statically.

template< typename _Type, size_t _Len > 
  class MPLArray{
    public:
      enum{ 
        Length 	= _Len,
        Size 	= sizeof( _Type ) * _Len,
      };
      _Type& operator[]( uint16_t i_Index ) { return this->t_Data[ i_Index ]; }
      operator _Type*(){ return this->t_Data; }
				
      _Type t_Data[ Length ];
};

Then use it like

MPLArray< uint8_t, 4 > m_Array = { 'a', 'b', 'c', '\0' };

Serial.println( m_Array.Size );
Serial.println( m_Array.Length );
Serial.println( m_Array[ 0 ] );
Serial.println( m_Array );

Just like a normal array, except with a size and length value.

Well… ok… I don't know C++ enough.

There is no constructor and "t_Data" is never set. Do you omit an implicit code? Perhaps I have other classes with the same issue.

"{ 'a', 'b', 'c', '\0' }" stay in the main file?

There is no code missing.
As the class does not define any constructors / copy constructors it is considered a POD ( plain old data ) type. Which can be initialised with an ‘initialiser list’.

so

MPLArray< uint8_t, 4 > m_Array = { 'a', 'b', 'c', '\0' };

initialises the first 4 POD’s inside the class, which is the array t_Data.

and you probably want to put it where ever the array was declared before.
Also replace { ‘a’, ‘b’, ‘c’, ‘\0’ } with whatever you need to store.

Why are you needing the template, and ‘objectizing’ your code for no reason is not the way to lean object oriented paradigms.