1

I'm new to C++. How to make a menu without if() {} else {} & switch() case? I made a menu on an array, but for some reason it doesn't compile. How to correct it?

typedef void (*cbd)(uint8_t, uint8_t);
typedef void (*cbt)(uint8_t, uint8_t);
typedef void (*cba)(uint8_t, uint8_t);
typedef void (*MenuFunction) (int8_t);

class Menu { public: Menu() { updownFns[5] = {updownNone, updownAlarmHours, updownAlarmMinutes, updownTimeHours, updownTimeMinutes}; }

static void Setup(cbd display, cbt setTime, cba setAlarm, uint8_t alarmHours, uint8_t alarmMinutes) {
    cbDisplay = display;
    cbSetTime = setTime;
    cbSetAlarms = setAlarm;
    alarmHours = alarmHours;
    alarmMinutes = alarmMinutes;
    cbSetAlarms(alarmHours, alarmMinutes);
}
// Used for menu.UpDown(dir) callback
static void UpDown(int8_t direction) {
    updownFn(direction);
}
// Used for menu.Tab() callback
static void Tab() {
    updownFnNum++;
    updownFn = updownFns[updownFnNum % 5];
}

private:

static void updownNone(int8_t direction) { }

static void updownAlarmHours(int8_t direction) {
    alarmHours += direction;
    cbDisplay(alarmHours, alarmMinutes);
    cbSetAlarms(alarmHours, alarmMinutes);
}

static void updownAlarmMinutes(int8_t direction) {
    alarmMinutes += direction;
    cbDisplay(alarmHours, alarmMinutes);
    cbSetAlarms(alarmHours, alarmMinutes);
}

static void updownTimeHours(int8_t direction) {
    timeHours += direction;
    cbSetTime(timeHours, timeMinutes);
    cbDisplay(timeHours, timeMinutes);
}

static void updownTimeMinutes(int8_t direction) {
    timeMinutes += direction;
    cbSetTime(timeHours, timeMinutes);
    cbDisplay(timeHours, timeMinutes);
}

static uint8_t alarmHours, alarmMinutes, timeHours, timeMinutes;
static uint8_t updownFnNum; // 0-None, 1-AlarmH, 2-AlarmM, 3-TimeH, 4-TimeM
static cbd cbDisplay;
static cbt cbSetTime;
static cba cbSetAlarms;
static MenuFunction updownFns[5];
static MenuFunction updownFn;

};

uint8_t Menu::alarmHours = 0; uint8_t Menu::alarmMinutes = 0; uint8_t Menu::timeHours = 0; uint8_t Menu::timeMinutes = 0; uint8_t Menu::updownFnNum = 0; cbd Menu::cbDisplay = NULL; cbt Menu::cbSetTime = NULL; cba Menu::cbSetAlarms = NULL; MenuFunction Menu::updownFn = NULL;

Output:

In file included from app.ino:7:0:
menu.h: In constructor 'Menu::Menu()':
menu.h:9:109: error: cannot convert '<brace-enclosed initializer list>' to 'MenuFunction {aka void (*)(signed char)}' in assignment
updownFns[5] = {updownNone, updownAlarmHours, updownAlarmMinutes, updownTimeHours, updownTimeMinutes};

Thank you!

Andre
  • 27
  • 6

2 Answers2

2

The C++ language makes a distinction between an initialization and an assignment. An initialization is the initial value you give to a variable at the point where you are defining it. An assignment is the use of the = operator anywhere else. Also, the language does not allow assigning the contents of an array as a whole. You can initialize an array though.

This:

Menu() {
    updownFns[5] = {updownNone, updownAlarmHours, updownAlarmMinutes,
        updownTimeHours, updownTimeMinutes};
}

is an attempt to assign a whole array. It cannot work. If you want to initialize the array, do it at the point where it is being defined, outside of the class definition:

MenuFunction Menu::updownFns[5] = {updownNone, updownAlarmHours,
    updownAlarmMinutes, updownTimeHours, updownTimeMinutes};
Edgar Bonet
  • 45,094
  • 4
  • 42
  • 81
0

First, your updownFns[5] can be contain 5 variable. And the last variable index can be 4 not 5 because of array index starts from 0.

Here is the code :

typedef void (*cbd)(uint8_t, uint8_t);
typedef void (*cbt)(uint8_t, uint8_t);
typedef void (*cba)(uint8_t, uint8_t, uint8_t);
typedef void (*MenuFunction) (int8_t);

class Menu { public: Menu() { updownFns[0] = updownNone; updownFns[1] = updownAlarmHours; updownFns[2] = updownAlarmMinutes; updownFns[3] = updownTimeHours; updownFns[4] = updownTimeMinutes; }

static void Setup(cbd display, cbt setTime, cba setAlarm, uint8_t alarmHours, uint8_t alarmMinutes) {
    cbDisplay = display;
    cbSetTime = setTime;
    cbSetAlarms = setAlarm;
    alarmHours = alarmHours;
    alarmMinutes = alarmMinutes;
    cbSetAlarms(alarmHours, alarmMinutes);
}
// Used for menu.UpDown(dir) callback
static void UpDown(int8_t direction) {
    updownFn(direction);
}
// Used for menu.Tab() callback
static void Tab() {
    updownFnNum++;
    updownFn = updownFns[updownFnNum % 5];
}

private:

static void updownNone(int8_t direction) { }

static void updownAlarmHours(int8_t direction) {
    alarmHours += direction;
    cbDisplay(alarmHours, alarmMinutes);
    cbSetAlarms(alarmHours, alarmMinutes);
}

static void updownAlarmMinutes(int8_t direction) {
    alarmMinutes += direction;
    cbDisplay(alarmHours, alarmMinutes);
    cbSetAlarms(alarmHours, alarmMinutes);
}

static void updownTimeHours(int8_t direction) {
    timeHours += direction;
    cbSetTime(timeHours, timeMinutes);
    cbDisplay(timeHours, timeMinutes);
}

static void updownTimeMinutes(int8_t direction) {
    timeMinutes += direction;
    cbSetTime(timeHours, timeMinutes);
    cbDisplay(timeHours, timeMinutes);
}

static uint8_t alarmHours, alarmMinutes, timeHours, timeMinutes;
static uint8_t updownFnNum; // 0-None, 1-AlarmH, 2-AlarmM, 3-TimeH, 4-TimeM
static cbd cbDisplay;
static cbt cbSetTime;
static cba cbSetAlarms;
static MenuFunction updownFns[5];
static MenuFunction updownFn;

};

uint8_t Menu::alarmHours = 0; uint8_t Menu::alarmMinutes = 0; uint8_t Menu::timeHours = 0; uint8_t Menu::timeMinutes = 0; uint8_t Menu::updownFnNum = 0; cbd Menu::cbDisplay = NULL; cbt Menu::cbSetTime = NULL; cba Menu::cbSetAlarms = NULL; MenuFunction Menu::updownFn = NULL; // MenuFunction Menu::updownFns = {};

But still code is not correct. if you look at the signature of this definition

typedef void (*cba)(uint8_t, uint8_t, uint8_t);

it takes 3 parameters. But inside the code, you give 2 parameter to the function

cbSetAlarms(alarmHours, alarmMinutes)