non-trivial designated initializers not supported

前端 未结 6 1519
隐瞒了意图╮
隐瞒了意图╮ 2020-12-24 04:23

I have a structure as follows:

struct app_data
{
    int port;
    int ib_port;
    unsigned size;
    int tx_depth;
    int sockfd;
    char *servername;
           


        
相关标签:
6条回答
  • 2020-12-24 04:58

    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.

    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
    0 讨论(0)
  • 2020-12-24 05:05

    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.

    Another workaround is to use an immediately invoked 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.

    0 讨论(0)
  • 2020-12-24 05:07

    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.

    0 讨论(0)
  • 2020-12-24 05:16

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

    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;
    
    0 讨论(0)
  • 2020-12-24 05:19

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

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

    #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]

    0 讨论(0)
  • 2020-12-24 05:20

    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...

    0 讨论(0)
提交回复
热议问题