私は次のような構造を持っています:
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に配置[免責事項、これをテストしていません]
初期化の順序は、宣言の正確な順序である必要があります。
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
これは、コンパイラーが名前指向の順序が狂ったメンバーの初期化をサポートしていないことを意味することを理解しています。
昔ながらの方法で構造体を初期化する必要があります。わかりやすくするために変数名を保持していますが、変数をスキップせずに順番に初期化する必要があります。
どの変数でも初期化を停止できますが、それから来る変数を初期化することはできません。
GCCコンパイラには、.fieldname = valueの割り当てを受け入れるためのトリックがありますが、フィールドが構造体で宣言されているのと同じ順序である場合にのみコンパイルされます。
この構造体を2つの方法で初期化できました。名前のあるものは読みやすさを向上させ、後で構造体フィールドの順序が変更された場合に間違ったデータを割り当てるリスクを減らします。
//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
};
経験則は次のとおりです。
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;
残念ながら、C++は指定された初期化子をサポートしていません。 GCCでは引き続き(拡張機能として)使用できますが、struct
にリストされているのと同じ順序でメンバーを初期化する必要があります。
別の回避策は、すぐに呼び出されるラムダを使用することです。
constexpr Fuse_operations Fuse_ops = []{
Fuse_operations ops{};
ops.destroy = wiifs_destroy;
ops.getattr = wiifs_getattr;
ops.access = wiifs_access;
// ...
return ops;
}();
完全に標準のC++であり、必要な順序でフィールドを初期化し、不要なフィールドをスキップし、残りをデフォルトで初期化できるため、個人的にこのソリューションを好みます。そして、コンパイラはまだ これを最適化できます です。これはC++ 17以降でのみ機能することに注意してください。