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);
    – Andre
    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.
    – Andre
    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.
    – Andre
    Commented Oct 26, 2022 at 9:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.