C++ 不支持非平凡的指定初始值设定项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31215971/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:54:01  来源:igfitidea点击:

non-trivial designated initializers not supported

c++initialization

提问by Ivan

I have a structure as follows:

我的结构如下:

struct app_data
{
    int port;
    int ib_port;
    unsigned size;
    int tx_depth;
    int sockfd;
    char *servername;
    struct ib_connection local_connection;
    struct ib_connection *remote_connection;
    struct ibv_device *ib_dev;

};

When I try to initialize it thus:

当我尝试这样初始化它时:

struct app_data data =
{
    .port = 18515,
    .ib_port = 1,
    .size = 65536,
    .tx_depth = 100,
    .sockfd = -1,
    .servername = NULL,
    .remote_connection = NULL,
    .ib_dev = NULL
};

I get this error:

我收到此错误:

sorry, unimplemented: non-trivial designated initializers not supported

I think it wants the order of initialization exactly as it is declared, and local_connectionis missing. I don't need to initialize it though, and setting it to NULL doesn't work.

我认为它需要完全按照声明的初始化顺序,并且local_connection缺少。不过我不需要初始化它,将它设置为 NULL 不起作用。

If I change it to this for g++, still get the same error:

如果我将其更改为 g++,仍然会出现相同的错误:

struct app_data data =
{
    port : 18515,
    ib_port : 1,
    size : 65536,
    tx_depth : 100,
    sockfd : -1,
    servername : NULL,
    remote_connection : NULL,
    ib_dev : NULL
};

采纳答案by Anon

This does not work with g++. You are essentially using C constructs with C++. Couple of ways to get around it.

这不适用于 g++。您本质上是在 C++ 中使用 C 结构。绕过它的几种方法。

1) Remove the "." and change "=" to ":" when initializing.

1) 去掉“.” 并在初始化时将“=”更改为“:”。

#include <iostream>

using namespace std;
struct ib_connection
   {
    int x;
   };

   struct ibv_device
   {
   int y;
  };

struct app_data
{
    int port;
    int ib_port;
    unsigned size;
    int tx_depth;
    int sockfd;
    char *servername;
    struct ib_connection local_connection;
    struct ib_connection *remote_connection;
    struct ibv_device *ib_dev;

};

int main()
{

    struct app_data data =
    {
        port : 18515,
        ib_port : 1,
        size : 65536,
        tx_depth : 100,
        sockfd : -1,
        servername : NULL,

        local_connection : {5},
        remote_connection : NULL,
        ib_dev : NULL
    };

   cout << "Hello World" << endl; 

   return 0;
}

2) Use g++ -X c. (Not recommended) or put this code in extern C [Disclaimer, I have not tested this]

2) 使用 g++ -X c。(不推荐)或将此代码放在 extern C [免责声明,我没有测试过]

回答by Parallel Universe

the order of initialization needs to be in the exact order of declaration.

初始化的顺序需要与声明的确切顺序一致。

typedef struct FOO
{
    int a;
    int b;
    int c;
}FOO;

FOO foo   = {.a = 1, .b = 2}; // OK
FOO foo1  = {.a = 1};         // OK
FOO foo2  = {.b = 2, .a = 1}; // Error sorry, unimplemented: non-trivial designated initializers not supported
FOO foo3  = {.a = 1, .c = 2}; // Error sorry, unimplemented: non-trivial designated initializers not supported

I understand that this means that the compiler has no support for name-oriented, out-of-order, member initialization.

我知道这意味着编译器不支持面向名称的无序成员初始化。

Need to initialize the struct in the old fashioned way. I keep the variable names for clarity, but I have to initialize them in order, and not skip a variable.

需要以老式的方式初始化结构。为了清楚起见,我保留了变量名,但我必须按顺序初始化它们,而不是跳过变量。

I can stop the initialization at any variable, but can't initialize variables that come of that.

我可以在任何变量处停止初始化,但不能初始化由此产生的变量。

回答by flodis

I have noticed my GCC compiler has some trick to accept .fieldname=value assigments but will only compile if fields come in the same order they are declared in the struct.

我注意到我的 GCC 编译器有一些技巧来接受 .fieldname=value 赋值,但只有在字段的顺序与它们在结构中声明的顺序相同时才会编译。

I was able to init this struct in two ways. The one with names improves readability and reduces the risk of assigning the wrong data if the struct field order is later changed.

我能够以两种方式初始化这个结构。带有名称的名称提高了可读性,并降低了结构字段顺序更改后分配错误数据的风险。

//Declare struct
typedef struct
{
    uint32_t const * p_start_addr;
    uint32_t const * p_end_addr;
    fs_cb_t  const   callback;    
    uint8_t  const   num_pages;  
    uint8_t  const   priority;
} fs_config_t;

//Assign unnamed
fs_config_t fs_config  
{
    (uint32_t*)0x00030000,  // uint32_t const * p_start_addr;
    (uint32_t*)0x00038000,  // uint32_t const * p_end_addr;         
    fs_evt_handler,         // fs_cb_t  const   callback;
    8,                      // uint8_t  const   num_pages;
    0xFE                    // uint8_t  const   priority;               
};

//Assign to named fields
static fs_config_t fs_config1  
{
    .p_start_addr = (uint32_t*)0x00030000,
    .p_end_addr = (uint32_t*)0x00038000,            
    .callback = fs_evt_handler,
    .num_pages = 8,
    .priority = 0xFE                
};      

The rule of thumb is:

经验法则是:

  1. Assign to .name=value fields
  2. Assign in the order they where declared
  3. Include all fields in the assigment
  1. 分配给 .name=value 字段
  2. 按他们声明的顺序分配
  3. 包括分配中的所有字段

回答by Falko

Since none of the other approaches worked for me with the Arduino IDE, I decided to simply set each field separately:

由于在 Arduino IDE 中没有其他方法对我有用,我决定简单地分别设置每个字段:

struct app_data data;

data.port = 18515;
data.ib_port = 1;
data.size = 65536;
data.tx_depth = 100;
data.sockfd = -1;
data.servername = NULL;
data.remote_connection = NULL;
data.ib_dev = NULL;

回答by Léo Lam

Unfortunately, C++ doesn't support designated initialisers. GCC still lets you use them (as an extension) but you must initialise members in the same order as they are listed in the struct.

不幸的是,C++ 不支持指定的初始化程序。GCC 仍然允许您使用它们(作为扩展),但您必须按照它们在struct.

Another workaround is to use an immediately invoked lambda:

另一种解决方法是使用立即调用的 lambda:

constexpr fuse_operations fuse_ops = []{
  fuse_operations ops{};
  ops.destroy = wiifs_destroy;
  ops.getattr = wiifs_getattr;
  ops.access = wiifs_access;
  // ...
  return ops;
}();

I personally prefer this solution because it is perfectly standard C++, it lets you initialise fields in the order you want, skip the ones you don't need and default initialise the rest. And the compiler is still able to optimise this. Do note that this will only work with C++17 or newer.

我个人更喜欢这个解决方案,因为它是完全标准的 C++,它允许你按照你想要的顺序初始化字段,跳过你不需要的字段并默认初始化其余的字段。并且编译器仍然能够对此进行优化。请注意,这仅适用于 C++17 或更新版本。

回答by Guz

Also note that, as the original question stated, the order of the member expressions matter. I noticed that if I would like to only initialize "size" in the previous example, I need to put expressions for .port and .ib_port before. Otherwise I get the error "sorry, unimplemented: non-trivial designated initializers not supported" Not that intuitive...

另请注意,正如原始问题所述,成员表达式的顺序很重要。我注意到如果我只想在前面的例子中初始化“size”,我需要在之前放置 .port 和 .ib_port 的表达式。否则我会收到错误“对不起,未实现:不支持非平凡的指定初始值设定项”不是那么直观......