Возврат заключенного в скобки списка инициализатора как структуры - PullRequest
3 голосов
/ 18 февраля 2020

Ниже приведен упрощенный код, скомпилированный с g++ -c test.cpp или g++ -std=c++17 -c test.cpp

#include <cstddef>

struct sd_bus_vtable {
        union {
                struct {
                        size_t element_size;
                } start;
                struct {
                        const char *member;
                        const char *signature;
                } signal;
        } x;
};

sd_bus_vtable get()
{
    return {
        .x = {
            .signal = {
                .member = "",
                .signature= "",
            }
        }
    };
}

Он прекрасно компилируется на G CC 9.2.0 и clang 5/6, но не работает на 8.3.0 или 7.4 .0 с сообщением об ошибке ниже:

test.cpp:25:5: error: could not convert ‘{{{"", ""}}}’ from ‘<brace-enclosed initializer list>’ to ‘sd_bus_vtable’
     };

Чтобы обойти это, можно изменить функцию get(), как показано ниже, но выглядит не так чисто ...

sd_bus_vtable get()
{
    struct sd_bus_vtable t = {
        .x = {
            .signal = {
                .member = "",
                .signature= "",
            }
        }
    };
    return t;
}

Вопрос в том, действителен ли приведенный выше код или нет? Если да, вызывает ли это какую-то ошибку в G CC, которая исправлена ​​в GCC9?

1 Ответ

3 голосов
/ 18 февраля 2020

Назначенный синтаксис инициализатора еще не в стандарте C ++. Его планируется включить в C ++ 20. Однако он еще не был завершен или опубликован.

Таким образом, вы полагаетесь на компилятор, поддерживающий эту предстоящую функцию в качестве расширения.

В опубликованном В стандартах C ++ нет способа дать инициализатор, подобный этому, для члена объединения, кроме первого. (У вас может быть инициализатор члена по умолчанию в определении класса).

Тем временем будет работать следующий код:

sd_bus_vtable get()
{
    sd_bus_vtable r{};
    r.x.signal = {"", ""};
    return r;    
}

Примечание: Этот метод (с использованием оператор присваивания для переключения активного члена объединения) работает, только если все члены объединения имеют тривиальные конструкторы и деструкторы. В противном случае вам нужно вручную уничтожить и создать.

Также можно опустить имя x (это называется анонимный союз ), тогда имена членов объединения доступны, как если бы они были членами ограждающей структуры.

...