Нетривиальные назначенные инициализаторы не поддерживаются
У меня есть структура следующим образом:
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
};
Ответы
Ответ 1
Это не работает с g++. Вы по существу используете 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 [Отказ от ответственности, я не тестировал это]
Ответ 2
порядок инициализации должен быть в точном порядке объявления.
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
Я понимаю, что это означает, что компилятор не поддерживает инициализацию, основанную на именах, вне порядка,
Нужно инициализировать структуру по-старому. Я сохраняю имена переменных для ясности, но я должен их инициализировать по порядку и не пропускать переменную.
Я могу остановить инициализацию при любой переменной, но не могу инициализировать переменные, которые из этого.
Ответ 3
Я заметил, что мой компилятор GCC имеет некоторый трюк, чтобы принять .fieldname = значения, но будет компилироваться только в том случае, если поля находятся в том же порядке, в котором они объявлены в структуре.
Мне удалось запустить эту структуру двумя способами. Имя с именами улучшает читаемость и снижает риск присвоения неверных данных, если впоследствии изменится порядок полей структуры.
//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
- Назначьте в том порядке, в котором они объявлены
- Включить все поля в настройке
Ответ 4
К сожалению, С++ не поддерживает назначенные инициализаторы. GCC по-прежнему позволяет использовать их (в качестве расширения), но вы должны инициализировать элементы в том же порядке, что и в struct
.
Другим обходным решением является использование немедленно вызываемой лямбда:
constexpr fuse_operations fuse_ops = []{
fuse_operations ops{};
ops.destroy = wiifs_destroy;
ops.getattr = wiifs_getattr;
ops.access = wiifs_access;
// ...
return ops;
}();
Я лично предпочитаю это решение, потому что он совершенно стандартный С++, он позволяет вам инициализировать поля в нужном вам порядке, пропустить те, которые вам не нужны, и по умолчанию инициализировать остальные. И компилятор по-прежнему способен оптимизировать это. Обратите внимание, что это будет работать только с С++ 17 или новее.
Ответ 5
Поскольку ни один из других подходов не работал у меня с 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;
Ответ 6
Также обратите внимание, что, как изложено первоначальным вопросом, имеет значение порядок выражений членов. Я заметил, что если бы я хотел только инициализировать "размер" в предыдущем примере, мне нужно поставить выражения для .port и .ib_port раньше. В противном случае я получаю ошибку "извините, не реализовано: нетривиальные назначенные инициализаторы не поддерживаются" Не то, что интуитивно...