How to initialize a union with function pointers without errors or warnings? The code is targeted at embedded and have to compile it both in C and C++.
However I face the problem that direct initializing yields an warning of incompatible pointers with C and an error in C++ while designated initialization has been deprecated in C++.
Is there any way to do this without warnings and errors in C and C++?
Minimal example:
struct List {
union {
int (*foo)(int num, int data);
int (*fee)(int num, float data);
};
};
int foo_fun(int pnum, int data);
int fee_fun(int pnum, float data);
static const struct List list[] = {
{
{foo_fun},
},
{
{fee_fun},
/* C = warning: incompatible pointer types initializing 'int (*)(int, int)'
* with an expression of type 'int (int, float)'
*/
/* C++ = error: cannot initialize a member subobject of type 'int (*)(int, int)'
* with an lvalue of type 'int (int, float)':
* type mismatch at 2nd parameter ('int' vs 'float')
*/
},
/* With C++ */
{
{.fee = fee_fun},
/* ^^^^^^^^^^^^^
* C++ = warning: designated initializers are a C99 feature
*/
},
};
The code does work with the warnings incompatible pointer types or designated initializers are a C99 feature.
The crude way is to drop the union and use a void pointer. However, that is far down my list of preferred options due to obvious drawbacks.
Correctly remarked by alinsoar. Making sure the correct function is called is the job of other elements in List currently omitted in the example.
Designated initializes will become fully available again in C++20.
Until then they have no effect. Except for unions where they still seem to work. (minus the warning)
The only way to initialize a union member beyond the first in C++ (before C++20) is a constructor in the union.
The only way to initialize a union member beyond the first in C is a designated initializer.
This doesn't leave a whole lot of wiggle room. Beware, ugliness ahead:
// For convenience
typedef int (*fooPtr)(int, int);
typedef int (*feePtr)(int, float);
#ifndef __cplusplus
#define INITIALIZE(x) .x =
#else
#define INITIALIZE(x)
#endif
struct List {
union X {
#ifdef __cplusplus
constexpr X(fooPtr foo_) : foo(foo_) {}
constexpr X(feePtr fee_) : fee(fee_) {}
#endif
fooPtr foo;
feePtr fee;
} x;
};
int foo_fun(int pnum, int data);
int fee_fun(int pnum, float data);
static const struct List list[] = {
{
{INITIALIZE(foo) foo_fun},
},
{
{INITIALIZE(fee) fee_fun},
},
};
https://godbolt.org/z/pd42HT
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With