-2

I am using Arduino C++11

I want to create and execute a dynamically function pointer list from different instantiated class members. A function holding the dynamic list of funtion pointerns is called in the main program. I have tried several solutions, but I am stuck.

I hope the the framework below is sufficient documentation. If not please let me know.

class base {
// base class for holding global static functions. Shall not be instatited.
// if necessary, change class to namespace or struct.
  private:
    friend class class_inp;
    friend class class_out;
    static void base_add_funtion_pointer_from_instatiated_class_member 
    (/* function pointer upddate_event_control() */) {
      // what do do?
    }
  public:
    static void execute_dynamic_list_of_instatiated_function_pointers() {
      // how to do it?
    }
};

Two class with identical functions to call

class class_inp : public base {
  public:
    class_inp (bool eventSwitch) {
      base_add_funtion_pointer_from_instatiated_class_member
        (/* function pointer from upddate_event_control() */);
    }
    void upddate_event_control();
};
class class_out : public base {
  public:
    class_out (/* arguments*/) {
      base_add_funtion_pointer_from_instatiated_class_member
        (/* function pointer from upddate_event_control() */);
    }
    void upddate_event_control();
};

Main program

class_inp inp;
class_out out;

// Arduino main
void loop() {
  base::execute_dynamic_list_of_instatiated_function_pointers();
  delay(1); // waith 1 millisecond
}
3
  • 5
    A few notes, what you are describing is not what you want, but how you want to solve what you want (they are not the same). What you seem to want is to have a list of things to call (with the correct arguments like "this" pointers) that can be modified at runtime (which then will affect what's being called in your main loop). And function pointers alone are not enough to call (non-static) member functions of classes. You might want to have a look at std::function + lambda expressions for that. Commented May 23 at 20:31
  • "I want to create and execute a dynamically function pointer list from different instantiated class members." -- What do you mean by "different instantiated class members"? Maybe "different instantiated class instances? Different derived classes? (The members are parts of the class. You can either instantiate all members (in one instance) or not instantiate the class at all.) In any event, if you cannot do the task with a single instance, figure that out before making things more complicated. Commented May 23 at 20:42
  • "I hope the the framework below is sufficient documentation." -- Code is rarely adequate documentation. It can illustrate documentation, but it's much better to write out specs. Things like; "In one function, I need to create a list of function pointers." "This list must be accessible from _____." "____ needs to iterate over the list and invoke each pointed-to function." "Here is what I can do: _____" "This is where I am stuck: _____" Also, you should state whether "list" is short for "collection" or if you really need a linked list. Commented May 23 at 20:46

1 Answer 1

0

you want to avoid dynamic allocations on embedded devices, but you can have linked lists. basically each object will contain a next pointer, and will register itself in the constructor.

class base {
    // base class for holding global static functions. Shall not be instatited.
    // if necessary, change class to namespace or struct.
    private:
        friend class class_inp;
        friend class class_out;
        static void base_add_funtion_pointer_from_instatiated_class_member 
        (base* object) {
            if (begin == nullptr)
            {
                begin = object;
            }
            if (end != nullptr)
            {
                end->next = object;
            }
            end = object;
        }
        static base* begin;
        static base* end;
        base* next = nullptr;
    protected:
    virtual void update_event_control() = 0;
    public:
        base(const base&) = delete;
        base& operator=(const base&) = delete;
        base() {}
        
        static void execute_dynamic_list_of_instatiated_function_pointers() {
            base* object = begin;
            while (object != nullptr)
            {
                object->update_event_control();
                object = object->next;
            }
        }
};
// make sure those two are in a .cpp file
base* base::begin = nullptr;
base* base::end = nullptr;

class class_inp : public base {
  public:
    class_inp (bool eventSwitch = false) {
      base_add_funtion_pointer_from_instatiated_class_member(this);
    }
    void update_event_control() override {
        std::cout << "inp\n";
    }
};

online demo

improvements for future if needed: unregister the object in the destructor.

if only 1 member function is ever needed, you can remove virtual and store a function pointer, this removes a few cycles (3 instructions per call), this is not needed for a computer but may make a difference on a microcontroller.

class base {
    // base class for holding global static functions. Shall not be instatited.
    // if necessary, change class to namespace or struct.
    private:
        friend class class_inp;
        friend class class_out;
        static void base_add_funtion_pointer_from_instatiated_class_member 
        (base* object) {
            if (begin == nullptr)
            {
                begin = object;
            }
            if (end != nullptr)
            {
                end->next = object;
            }
            end = object;
        }
        static base* begin;
        static base* end;
        base* next = nullptr;
        using func_type = void (*)(base*);
        func_type func = nullptr;
    public:
        base(const base&) = delete;
        base& operator=(const base&) = delete;
        base(func_type f) : func{f} {}

        static void execute_dynamic_list_of_instatiated_function_pointers() {
            base* object = begin;
            while (object != nullptr)
            {
                object->func(object);
                object = object->next;
            }
        }
};
// make sure those two are in a .cpp file
base* base::begin = nullptr;
base* base::end = nullptr;

class class_inp : public base {
  public:
    class_inp (bool eventSwitch = false)
    :base{[](base* p) { static_cast<class_inp*>(p)->update_event_control(); }}
    {
      base_add_funtion_pointer_from_instatiated_class_member(this);
    }
    void update_event_control() {
        std::cout << "inp\n";
    }
};

online demo

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you very much This is exactly what I need! However Arduino IDE compiler is only supporting C++11 and does not support the inline specifier (C++17/C++1z). Is it possible that you could modify the program to be C++11 compliant? Also, I would apreciate if you would write code to unregister the object in the destructor.
@jebmdk i modified the definition and placed them out of the declaration so the code is now C++11, they need to be placed in a .cpp file though if your project has multiple files. as for the destructors, you don't need the destructors if those are all globals.

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.