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!

2 Answers 2

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};
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)
6
  • It's a typo, I've corrected it. But the error is the same. typedef void (*cba)(uint8_t, uint8_t); Commented Oct 26, 2022 at 7: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 Commented Oct 26, 2022 at 7:50
  • updownFns[0] = updownNone; It gave: /tmp/cc3MHoSt.ltrans0.ltrans.o: In function global constructors keyed to 65535_0_app.ino.cpp.o.4201': <artificial>:(.text.startup+0x144): undefined reference to Menu::updownFns' <artificial>:(.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. Commented Oct 26, 2022 at 7: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. Commented Oct 26, 2022 at 8:03
  • I initialized the array outside of the class definition. No errors. I then used updownFns and no errors. Commented Oct 26, 2022 at 9:17

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.