web-dev-qa-db-fra.com

initialisateurs désignés non triviaux non pris en charge

J'ai une structure comme suit:

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;

};

Quand j'essaye de l'initialiser ainsi:

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

Je reçois cette erreur:

sorry, unimplemented: non-trivial designated initializers not supported

Je pense qu'il veut l'ordre d'initialisation exactement comme il est déclaré, et local_connection est manquant. Je n'ai pas besoin de l'initialiser cependant, et le régler sur NULL ne fonctionne pas.

Si je le change en g ++, j'obtiens toujours la même erreur:

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

Cela ne fonctionne pas avec g ++. Vous utilisez essentiellement des constructions C avec C++. Deux façons de contourner le problème.

1) Retirez le "." et remplacez "=" par ":" lors de l'initialisation.

#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) Utilisez g ++ -X c. (Non recommandé) ou mettez ce code dans extern C [Disclaimer, je n'ai pas testé cela]

27
Anon

l'ordre d'initialisation doit être dans l'ordre exact de déclaration.

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

Je comprends que cela signifie que le compilateur ne prend pas en charge l’initialisation de membres orientée nom et en désordre.

Besoin d'initialiser la structure à l'ancienne. Je conserve les noms des variables pour plus de clarté, mais je dois les initialiser dans l’ordre et ne pas sauter de variable.

Je peux arrêter l'initialisation à n'importe quelle variable, mais je ne peux pas initialiser les variables qui en découlent.

42
Parallel Universe

J'ai remarqué que mon compilateur GCC a une astuce pour accepter les assignations .fieldname = value, mais ne compilera que si les champs sont dans le même ordre où ils sont déclarés dans la structure.

J'ai pu initier cette structure de deux manières. Celui qui porte un nom améliore la lisibilité et réduit le risque d’attribution de données erronées si l’ordre de struct struct est modifié ultérieurement.

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

La règle de base est la suivante:

  1. Affecter à .name = champs de valeur
  2. Attribuer dans l'ordre où ils ont été déclarés
  3. Inclure tous les champs dans l'assigment
10
flodis

Comme aucune des autres approches ne fonctionnait pour moi avec l'IDE Arduino, j'ai décidé de définir simplement chaque champ séparément:

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;
4
Falko

Malheureusement, C++ ne prend pas en charge les initialiseurs désignés. GCC vous permet toujours de les utiliser (en tant qu'extension), mais vous devez initialiser les membres dans le même ordre que celui indiqué dans la liste struct.

Une autre solution consiste à utiliser un lambda immédiatement appelé:

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

Personnellement, je préfère cette solution car elle est parfaitement standard en C++, elle vous permet d’initialiser les champs dans l’ordre que vous souhaitez, d’ignorer ceux dont vous n’avez pas besoin et d’initialiser par défaut les autres. Et le compilateur est toujours capable d'optimiser cela . Notez que cela ne fonctionnera qu'avec C++ 17 ou plus récent.

2
Léo Lam