Hi all,
I have a class that contains an array. Since there's only 2KB of RAM, I don't want that array to be bigger than what's strictly needed, but I don't want to use dynamic allocation either.
Unless the client code supplies the class constructor a pointer to an already allocated array, the class must declare its array size in advance.
If the class is to be used as a library, a reasonable default size must be specified. If a sketch needs more room, one has to modify the library source. Ugly.
Two solutions come to mind: templates and #define.
Using templates
#ifndef _BOARDS_H
#define _BOARDS_H
template <int MAX_BOARD_CNT>
class Boards {
public:
void addBoard(int boardId) {
if (_numBoards < MAX_BOARD_CNT - 1) {
_boardIds[_numBoards] = boardId;
_numBoards++;
}
};
int getMaxBoardCnt() {
return MAX_BOARD_CNT;
};
int getNumBoards() {
return _numBoards;
};
private:
int _boardIds[MAX_BOARD_CNT];
int _numBoards;
};
#endif
The client code looks like this:
#include "Boards.h"
Boards<100> boards;
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
};
void setup() {
Serial.begin(115200);
Serial.println(boards.getMaxBoardCnt());
Serial.println(boards.getNumBoards());
boards.addBoard(5);
boards.addBoard(10);
Serial.println(boards.getNumBoards());
Serial.println(freeRam());
}
void loop() {
}
Using #define
#ifndef _BOARDS_H
#define _BOARDS_H
#ifndef Boards_MAX_BOARD_CNT
#define Boards_MAX_BOARD_CNT 10 // default value
#endif
class Boards {
public:
static const int MAX_BOARD_CNT = Boards_MAX_BOARD_CNT;
void addBoard(int boardId) {
if (_numBoards < MAX_BOARD_CNT - 1) {
_boardIds[_numBoards] = boardId;
_numBoards++;
}
};
int getMaxBoardCnt() {
return MAX_BOARD_CNT;
};
int getNumBoards() {
return _numBoards;
};
private:
int _boardIds[MAX_BOARD_CNT];
int _numBoards;
};
#endif
The client code is now:
#define Boards_MAX_BOARD_CNT 100 // if this is omitted, the library hardcoded default value is used
#include "Boards.h"
Boards boards;
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
};
void setup() {
Serial.begin(115200);
Serial.println(boards.getMaxBoardCnt());
Serial.println(boards.getNumBoards());
boards.addBoard(5);
boards.addBoard(10);
Serial.println(boards.getNumBoards());
Serial.println(freeRam());
}
void loop() {
}
So what ?
With 100 elements, the results are:
template: code size = 2592 bytes, freeRam = 1578
#define: code size = 2592 bytes, freeRam = 1578
The template method perhaps looks more elegant, but I don't like the idea of having to put an entire class - declaration and implementation - inside a single .h file.
There might be other issues that a trivial example doesn't touch...
What do you think ?