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
  • 5

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
  • 39,449
  • 4
  • 36
  • 72
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)
  • It's a typo, I've corrected it. But the error is the same. `typedef void (*cba)(uint8_t, uint8_t);` – Andre Oct 26 '22 at 07:48
  • It's not typo, typo means something different. if you change typedef void (*cba)(uint8_t, uint8_t, uint8_t); to typedef void (*cba)(uint8_t, uint8_t); Code wil compile without errors – embeddedstack Oct 26 '22 at 07:50
  • `updownFns[0] = updownNone;` It gave: /tmp/cc3MHoSt.ltrans0.ltrans.o: In function `global constructors keyed to 65535_0_app.ino.cpp.o.4201': :(.text.startup+0x144): undefined reference to `Menu::updownFns' :(.text.startup+0x148): undefined reference to `Menu::updownFns' collect2: error: ld returned 1 exit status exit status 1 Error compiling for board Arduino Pro or Pro Mini. – Andre Oct 26 '22 at 07:51
  • 1
    There are several issue with your code. You can use like this Remove initilization from ctor and init static variable outside. MenuFunction Menu::updownFns[] = {updownNone, updownAlarmHours, updownAlarmMinutes, updownTimeHours, updownTimeMinutes }; But when you want to use updownFns it will give errors because of the function is private within this context also. – embeddedstack Oct 26 '22 at 08:03
  • I initialized the array outside of the class definition. No errors. I then used `updownFns` and no errors. – Andre Oct 26 '22 at 09:17
  • Yes, i already said about it :) – embeddedstack Oct 26 '22 at 10:05