C++ 为C和C初始化联合函数指针++;

C++ 为C和C初始化联合函数指针++;,c++,c,initialization,unions,C++,C,Initialization,Unions,如何在没有错误或警告的情况下使用函数指针初始化联合? 该代码以嵌入式为目标,必须在C和C++中编译。 但是我遇到的问题是,直接初始化会产生一个C与C++不兼容的指针警告,而C++中的指定初始化已经被禁止。 最简单的例子: struct List { union { int (*foo)(int num, int data); int (*fee)(int num, float data); }; }; int foo_fun(int pnum

如何在没有错误或警告的情况下使用函数指针初始化联合? 该代码以嵌入式为目标,必须在C和C++中编译。 <>但是我遇到的问题是,直接初始化会产生一个C与C++不兼容的指针警告,而C++中的指定初始化已经被禁止。 <没有任何方法可以做到这一点而没有C和C++中的警告和错误?< /P> 最简单的例子:

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
 */
},

};
代码确实适用于警告
不兼容指针类型
指定的初始值设定项是C99功能

最简单的方法是删除联合体并使用空指针。然而,由于明显的缺点,这远远不是我的首选选项

阿林索尔正确地指出。确保调用了正确的函数是示例中当前省略的列表中其他元素的任务


指定的初始化将在C++20中再次完全可用。

在那之前,它们没有任何效果。除了工会,他们似乎仍在工作。(减去警告)

< p>只有在C++中(C++ 20之前)初始化联盟成员的唯一方法才是UNION.< /P>中的构造函数。
初始化C中第一个之外的联合成员的唯一方法是指定初始值设定项

这并没有留下太多的回旋余地。当心前方的丑陋:

// 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},
    },
};

不是很好,但也有一些可能性。C++具有构造函数重载。C具有
\u通用
和指定的初始值设定项

typedef int foo_t (int num, int data);
typedef int fee_t (int num, float data);

typedef struct List
{
  union 
  {
    foo_t* foo;
    fee_t* fee;
  };

  #ifdef __cplusplus
    List(foo_t* f) :foo(f){}
    List(fee_t* f) :fee(f){}  

    #define FOO_INIT(f) List(f)
    #define FEE_INIT(f) List(f)
  #else
    #define FOO_INIT(f) { .foo = _Generic((f), foo_t*: (f)) }
    #define FEE_INIT(f) { .fee = _Generic((f), fee_t*: (f)) }
  #endif   
} List;

int the_foo (int num, int data){ return 0;}
int the_fee (int num, float data){ return 0;}

int main (void)
{
  List list_foo = FOO_INIT(the_foo);
  List list_fee = FEE_INIT(the_fee);
  return 0;
}

在任何一种语言中,这都应该是类型安全的

C++20中将提供指定的初始值设定项(至少是C中存在的部分)。@Mat我知道。AcAIK指定的初始化没有在C++中被禁止,它从来没有在C++中,而是在C++出现之后才在C中引入,写在<代码>中的联合构造函数是什么?除了C++中的第一个联合成员外,没有其他方法来初始化任何东西。编辑:嗯,除了第一个没有指定初始值设定者的C99联盟成员之外,没有其他方法来初始化C99联盟成员……联盟是一个丑陋的黑客。演员阵容是另一个丑陋的黑客。我不知道为什么喜欢一个丑陋的黑客胜过另一个。@Jeroen3等等,它在哪个编译器中不工作?ARMGCC 8.2似乎很高兴:。ARMclang也是如此:(说清楚,我对ARM一无所知)。我有带uVision 4的armcc v5.06捆绑包。它类似于C++的错误,需要指定的初始化器。恐怕我不能使用构造函数方法。因为我必须将它加载到flash中,所以它必须是常量。这是一个嵌入式目标。@Jeroen3我不明白。你的编译器是C编译器还是C++编译器?或者两者都有?我假设编译器是编译代码,而不是C++。在这种情况下,您应该从构造函数的代码< >初始化< /代码>中得到指定的初始化器:标记它们<代码> CONTXPRP</代码>,然后得到编译时的列表(答案更新)。这与CAR99提供给ARMCC 5.06,并与明W32-730 C和C++一起使用。