Smartskaft2
Smartskaft2

Reputation: 510

Initialize function pointer array in constructor initializer list - error

I am trying to implement a simple menu class, for flexible usage when programming AVR boards. Thus, I cannot use several commonly used STL files (e.g. functional or initializer_list etc.).

My menu object has pointers toward the previous and next object, but also function pointers that is executed in certain situations. I have issues with these pointers.

I managed to get everything working with one single function pointer. However, when trying to use an array of function pointers I can't find a way to initialize it. Please see minimal example below or on onlinegdb.com. For simplicity, I hard coded the array size to 2.


Error Message

error: incompatible types in assignment of ‘void (**)()’ to ‘void (* [2])()’

Why does the same syntax tFcnPtr[2] give two different types??

The constructor parameter becomes void (**)(), while the member is defined void (* [2])().


Function pointer typedef

typedef void(*tFcnPtr)();

tMenu class (which works fine!)

class tMenu {  
  public:

    tMenu(tFcnPtr ptr) : _ptr(ptr) {}

    void run() {
        _ptr();
    }

    tFcnPtr _ptr;
};

tMenu2 class, which does not work. I cannot successfully initialize the function pointer array.

class tMenu2 {
  public:

    tMenu2(tFcnPtr ptrs[2]) : _ptrs(ptrs) {} // error: incompatible types in assignment of ‘void (**)()’ to ‘void (* [2])()’

    void run() {
        for (auto& fcn : _ptrs) {
            if (fcn != nullptr) {
                fcn();
            }
        }
    }

    tFcnPtr _ptrs[2];
};

Test

// Main test function
void p(const char c[]) {
    std::cout << c << std::endl;
}

// Main
int main()
{
    // Test functions
    tFcnPtr yup = [](){p("Yup!");};
    tFcnPtr zup = [](){p("Zup!");};
    tFcnPtr meh = [](){p("Meh.");};

    // tMenu
    tMenu m1{yup};
    m1.run();

    std::cout << std::endl;

    // tMenu2    
    tFcnPtr ptrs[] = {zup, meh};
    tMenu2 m2{ptrs};
    m2.run();
}

Upvotes: 0

Views: 594

Answers (1)

songyuanyao
songyuanyao

Reputation: 172924

In fact the function parameter ptrs's type is not an array, but pointer (i.e. tFcnPtr *), which can't be used to initialize an array directly. That's what the compiler complains.

The type of each function parameter in the parameter list is determined according to the following rules:

2) If the type is "array of T" or "array of unknown bound of T", it is replaced by the type "pointer to T"

You can initialize the array member as

class tMenu2 {
  public:

    tMenu2(tFcnPtr ptrs[2]) : _ptrs{ptrs[0], ptrs[1]} {}

    ...

    tFcnPtr _ptrs[2];
};

Or use std::array (or std::vector if the size is not fixed) instead.

class tMenu2 {
  public:

    tMenu2(std::array<tFcnPtr, 2> ptrs) : _ptrs(ptrs) {}

    ...

    std::array<tFcnPtr, 2> _ptrs;
};

Upvotes: 1

Related Questions