Move an array in runtime

Hi there, I'm making an lcd menu class, this is what I have for the moment. I know that it's wrong but you kinda get the idea there. What would you guys do? How would you guys move the array from the constructor to the array inside the class? Thanks

struct MENULIST {
  String item;
  void (*ptrFunc)();
};

MENULIST main_menu_items[] = {
{"ITEMONE", ItemOneFunction},
{"ITEMTWO", ItemTwoFunction}
};

class Menu{
  public:
    Menu(MENULIST items[]){
      current_item_selected = 0;
      menu_items = items;
    }
    void next(){
      if (((sizeof(menu_items)/sizeof(menu_items[0])) - 1) == current_item_selected){
       current_item_selected = 0;
      } else {
       current_item_selected++;
      }
    }
    void prev(){
      if (current_item_selected == 0){
        current_item_selected = ((sizeof(menu_items)/sizeof(menu_items[0])) - 1);
      } else { 
        current_item_selected--;
      }
    }
    String get(){
      return menu_items[current_item_selected].item;
    }
    void run(){
      (*menu_items[current_item_selected].ptrFunc)();
    }
  private:
    int current_item_selected;
    MENULIST menu_items[];
};
/*   MENU FUNCTIONS   */
void ItemOneFunction(){
  Serial.println("One");
}
void ItemTwoFunction(){
  Serial.println("Two");
}
/* ^^ MENU FUNCTIONS ^^ */

How would you guys move the array from the constructor to the array inside the class?

I wouldn't. I'd pass a pointer to the array to the constructor, and store that pointer.

Well, but even if I pass the pointer to the constructor, I still need to know the size of the array to declare the pointer, isn't it?

I changed the code to use the pointers, but I get an error:

struct MENULIST {
  String item;
  void (*ptrFunc)();
};

MENULIST main_menu_items[] = {
{"ITEMONE", ItemOneFunction},
{"ITEMTWO", ItemTwoFunction}
};

class Menu{
  public:
    Menu(MENULIST *items){
      current_item_selected = 0;
      menu_items = items;
    }
    void next(){
      if (((sizeof(menu_items)/sizeof(menu_items[0])) - 1) == current_item_selected){
       current_item_selected = 0;
      } else {
       current_item_selected++;
      }
    }
    void prev(){
      if (current_item_selected == 0){
        current_item_selected = ((sizeof(menu_items)/sizeof(menu_items[0])) - 1);
      } else { 
        current_item_selected--;
      }
    }
    String get(){
      return menu_items[current_item_selected].item;
    }
    void run(){
      (*menu_items[current_item_selected].ptrFunc)();
    }
  private:
    int current_item_selected;
    MENULIST *menu_items;
};
/*    MENU FUNCTIONS    */
void ItemOneFunction(){
  Serial.println("ONE");
}
void ItemTwoFunction(){
  Serial.println("TWO");
}
/* ^^ MENU FUNCTIONS ^^ */

Menu main_menu = Menu(&main_menu_items);

sketch_nov24b.ino: At global scope: sketch_nov24b:54: error: no matching function for call to 'Menu::Menu(MENULIST ()[2])' sketch_nov24b.ino:17: note: candidates are: Menu::Menu(MENULIST) sketch_nov24b.ino:15: note: Menu::Menu(const Menu&)

As PaulS mentioned you could use pointers. You are half way there already, you just need to pass a length so your class knows how many items there are, and change menu_items to a pointer ( leave the ‘&’ off when you pass the array otherwise you are passing a real pointer to an array, what you want is a pointer to the first element ):

class Menu{
  public:
    Menu(MENULIST items[], int len){

      menu_items = items;
      length = len;
    }

  private:
    MENULIST *menu_items;
    int length;
};

MENULIST list[4];
Menu menu( list, 4 );

void setup() {}
void loop() {}

I have an article explaining how to pass arrays using pointers, but also references to arrays also: Arduino FAQ - Passing arrays to functions

However rather than separating the menu items from the menu, you could also have the menu class take care of its items. Using a template, the usage becomes simple. I have also changed get to return a reference and prev/next/run will return the class allowing chaining of methods:

struct MENULIST {
  String item;
  void (*ptrFunc)();
};

template< unsigned N >
class Menu{
  public:
  
    MENULIST &operator[]( unsigned idx ){ return menu_items[ idx ]; }
  
    Menu &next(){
      if( ++current_item_selected == N ) current_item_selected = 0;
      return *this;
    }
    
    Menu &prev(){
      if( --current_item_selected == -1 ) current_item_selected = N - 1;
      return *this;
    }  
  
    String &get(){ return menu_items[current_item_selected].item; }    //Return a reference, cheaper!
    
    Menu &run(){
      (*menu_items[current_item_selected].ptrFunc)();
      return *this;
    }  
  
    int current_item_selected;
    MENULIST menu_items[ N ];
};

Menu< 3 > menu = {
  0,    //Current item
  {
    {"ITEMONE", ItemOneFunction},
    {"ITEMTWO", ItemTwoFunction},
    {"ITEMTHREE", ItemThreeFunction},
  },
};

void setup() {

  //Get current item
  String &str = menu.get();
  
  //Run current function
  menu.run();
  
  //Chain methods.
  menu.next().next().run().prev().run();
  
  //Access raw menu item.
  menu[ 0 ].ptrFunc = ItemOneFunction;

}

void ItemOneFunction(){}
void ItemTwoFunction(){}
void ItemThreeFunction(){}

void loop() {}

Thank you very much but now I'm a lil bit lost with this line:

    MENULIST &operator[]( unsigned idx ){ return menu_items[ idx ]; }

Also I don't understand why you are using the reference operator on every function. Srry I'm trying to learn faster than I can at C.

    MENULIST &operator[]( unsigned idx ){ return menu_items[ idx ]; }

This is an overload of the subscript operator '[]', Here it simply removes a layer of indirection to access the raw menu items. These two lines are the same, the first is allowed due to the overloaded operator:

String &str = menu[ 0 ].item;

//or without the operator:
String &str = menu.menu_items[0].item;

Adding the reference return values to the functions allows method chaining, like in my example:

menu.next().next().run().prev().run();

//People familiar with web languages may write it like this:
menu
  .next()
  .next()
  .run()
  .prev()
  .run();

. In many circumstances, the compiler will produce more efficient code than writing the equivalent:

menu.next();
menu.next();
menu.run();
menu.prev();
menu.run();

And when used like the code above, it is no less efficient, than if the functions returned nothing (void).

pYro_65: This is an overload of the subscript operator '[]', Here it simply removes a layer of indirection to access the raw menu items. These two lines are the same, the first is allowed due to the overloaded operator:

Ok, I got this, thanks :)

pYro_65: Adding the reference return values to the functions allows method chaining, like in my example:

menu.next().next().run().prev().run();

//People familiar with web languages may write it like this: menu  .next()  .next()  .run()  .prev()  .run();

Maybe I didn't explain myself quite well or I'm not understanding you, when I asked why you were putting the reference operator I was talking about this, not the return values:

 Menu &next(), Menu &prev()...

myownway: Ok, I got this, thanks :)Maybe I didn't explain myself quite well or I'm not understanding you, when I asked why you were putting the reference operator I was talking about this, not the return values:

 Menu &next(), Menu &prev()...

I think there is a misunderstanding, as we are talking about the same thing.

Rather than having next, prev, and run return nothing ( void ), we can return a reference. The Menu & part is the function return type and is a reference to a Menu. As we return the current instance: *this, it effectively returns a reference to the class instance used to call the function. And can be used to create a chain of calls.