Reputation: 510
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
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 ofT
", it is replaced by the type "pointer toT
"
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