不支持非平凡的指定初始值设定项
non-trivial designated initializers not supported
我的结构如下:
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;
};
当我尝试这样初始化它时:
struct app_data data =
{
.port = 18515,
.ib_port = 1,
.size = 65536,
.tx_depth = 100,
.sockfd = -1,
.servername = NULL,
.remote_connection = NULL,
.ib_dev = NULL
};
我收到这个错误:
sorry, unimplemented: non-trivial designated initializers not supported
我认为它想要的初始化顺序与它声明的完全一样,local_connection
丢失了。不过我不需要初始化它,将它设置为 NULL 也不起作用。
如果我将其更改为 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
};
这不适用于 g++。您实质上是在 C++ 中使用 C 构造。有几种方法可以解决它。
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) 使用 g++ -X c。 (不推荐)或者将这段代码放在 extern C [免责声明,我没有测试过]
另请注意,正如原始问题所述,成员表达式的顺序很重要。我注意到,如果我只想在前面的示例中初始化 "size",我需要在之前放置 .port 和 .ib_port 的表达式。否则我会得到错误 "sorry, unimplemented: non-trivial designated initializers not supported" 不那么直观...
我注意到我的 GCC 编译器有一些技巧可以接受 .fieldname=value 赋值,但只有当字段的顺序与它们在结构中声明的顺序相同时才会编译。
我可以通过两种方式初始化这个结构。带有名称的那个提高了可读性,并降低了以后更改结构字段顺序时分配错误数据的风险。
//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
};
经验法则是:
- 分配给 .name=value 字段
- 按照声明的顺序分配
- 在分配中包含所有字段
初始化的顺序需要与声明的顺序完全一致。
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
我理解这意味着编译器不支持面向名称的、无序的、成员初始化。
需要以老式方式初始化结构。为了清楚起见,我保留了变量名,但我必须按顺序初始化它们,而不是跳过一个变量。
我可以在任何变量处停止初始化,但无法初始化由此产生的变量。
遗憾的是,C++ 不支持指定的初始化程序。 GCC 仍然允许您使用它们(作为扩展),但您必须按照 struct
.
中列出的相同顺序初始化成员
另一种解决方法是使用立即调用的 lambda:
constexpr fuse_operations fuse_ops = []{
fuse_operations ops{};
ops.destroy = wiifs_destroy;
ops.getattr = wiifs_getattr;
ops.access = wiifs_access;
// ...
return ops;
}();
我个人更喜欢这个解决方案,因为它是完全标准的 C++,它可以让您按您想要的顺序初始化字段,跳过不需要的字段,并默认初始化其余字段。而且编译器还是able to optimise this。请注意,这仅适用于 C++17 或更新版本。
由于 none 其他方法对我适用于 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;
我被这个变体击中了。考虑这个损坏的代码:
enum {
S_START,
S_ANOTHER,
S_LAST
} STATES;
const char* STATE_NAMES[] = {
[S_START] = "S_START",
[S_LAST] = "S_LAST",
};
int main() {
}
错误信息如下:
a.cpp:10:1: sorry, unimplemented: non-trivial designated initializers not supported
10 | };
问题是我忘记在 STATE_NAMES 中定义 S_ANOTHER 条目。
我的结构如下:
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;
};
当我尝试这样初始化它时:
struct app_data data =
{
.port = 18515,
.ib_port = 1,
.size = 65536,
.tx_depth = 100,
.sockfd = -1,
.servername = NULL,
.remote_connection = NULL,
.ib_dev = NULL
};
我收到这个错误:
sorry, unimplemented: non-trivial designated initializers not supported
我认为它想要的初始化顺序与它声明的完全一样,local_connection
丢失了。不过我不需要初始化它,将它设置为 NULL 也不起作用。
如果我将其更改为 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
};
这不适用于 g++。您实质上是在 C++ 中使用 C 构造。有几种方法可以解决它。
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) 使用 g++ -X c。 (不推荐)或者将这段代码放在 extern C [免责声明,我没有测试过]
另请注意,正如原始问题所述,成员表达式的顺序很重要。我注意到,如果我只想在前面的示例中初始化 "size",我需要在之前放置 .port 和 .ib_port 的表达式。否则我会得到错误 "sorry, unimplemented: non-trivial designated initializers not supported" 不那么直观...
我注意到我的 GCC 编译器有一些技巧可以接受 .fieldname=value 赋值,但只有当字段的顺序与它们在结构中声明的顺序相同时才会编译。
我可以通过两种方式初始化这个结构。带有名称的那个提高了可读性,并降低了以后更改结构字段顺序时分配错误数据的风险。
//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
};
经验法则是:
- 分配给 .name=value 字段
- 按照声明的顺序分配
- 在分配中包含所有字段
初始化的顺序需要与声明的顺序完全一致。
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
我理解这意味着编译器不支持面向名称的、无序的、成员初始化。
需要以老式方式初始化结构。为了清楚起见,我保留了变量名,但我必须按顺序初始化它们,而不是跳过一个变量。
我可以在任何变量处停止初始化,但无法初始化由此产生的变量。
遗憾的是,C++ 不支持指定的初始化程序。 GCC 仍然允许您使用它们(作为扩展),但您必须按照 struct
.
另一种解决方法是使用立即调用的 lambda:
constexpr fuse_operations fuse_ops = []{
fuse_operations ops{};
ops.destroy = wiifs_destroy;
ops.getattr = wiifs_getattr;
ops.access = wiifs_access;
// ...
return ops;
}();
我个人更喜欢这个解决方案,因为它是完全标准的 C++,它可以让您按您想要的顺序初始化字段,跳过不需要的字段,并默认初始化其余字段。而且编译器还是able to optimise this。请注意,这仅适用于 C++17 或更新版本。
由于 none 其他方法对我适用于 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;
我被这个变体击中了。考虑这个损坏的代码:
enum {
S_START,
S_ANOTHER,
S_LAST
} STATES;
const char* STATE_NAMES[] = {
[S_START] = "S_START",
[S_LAST] = "S_LAST",
};
int main() {
}
错误信息如下:
a.cpp:10:1: sorry, unimplemented: non-trivial designated initializers not supported
10 | };
问题是我忘记在 STATE_NAMES 中定义 S_ANOTHER 条目。