C ++ 20 Назначенные инициализаторы char [] - PullRequest
2 голосов
/ 08 апреля 2020

C ++ 20 вводит назначенные инициализаторы . Я пытаюсь инициализировать массив символов внутри структуры с новым синтаксисом.

Довольно простая проблема, я думаю, код может объяснить это лучше всего :

struct Test
{
    unsigned v;
    char b[12];
};

int main()
{
    char str[12] = "hello"; // Works.
    char strb[12]{"hello"}; // Works.
    //
    Test testa
    {
        .v = 100u,
        .b = "hello" //Doesn't work...
    };
    Test testb
    {
        .v = 100u,
        .b = { "hello" } //Doesn't work...
    };
    Test testc
    {
        .v{ 100u },
        .b{ "hello" } //Doesn't work...
    };
    Test testd
    {
        .v{ 100u },
        .b{ "hello" } //Doesn't work...
    };
    Test teste
    {
        .v = 100u,
        .b = {} //This works.
    };
    Test testf
    {
        .v = 100u,
        .b = {'h', 'e', 'l', 'l', 'o', '\0'} //This works.
    };
    return 0;
}

Я считаю это поведение bazzar, строка char str[12] = "hello"; работает просто отлично. Но та же самая форма инициализации не работает в назначенных списках инициализатора.

Вопрос : Почему я не могу инициализировать массив символов строковым литералом?

Редактировать

Я был ранее используя G CC. Это работает с clang. Есть ли обходной путь для G CC и является ли clang или G CC правильным?

Ответы [ 2 ]

2 голосов
/ 28 апреля 2020

Назначенные инициализаторы являются незначительным отклонением совокупной инициализации . Единственное использование имен указателей состоит в том, чтобы решить, какой агрегатный элемент инициализировать из заданного инициализатора скобок или равных. Использование назначенной инициализации ничего не меняет в специфической c форме инициализации и, следовательно, независимо от того, является ли она действительной.

Если ваш объект Test, Test{100u, "hello"} и Test{.v = 100u, .b = "hello"} оба являются действительными или оба недействительны. В обоих случаях Test::b инициализируется в соответствии с [dcl.init.aggr] 4.2 :

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

Копирование-инициализация - это точно такой же процесс, который был бы, если бы вы просто инициализировали переменную массива. Что совершенно верно.

Так что вы могли бы работать. Это ошибка компилятора.

"Обходной путь" G CC заключается в ожидании исправления ошибки. Или go вернуться к стандартной агрегатной инициализации, пока их компилятор не будет исправлен.

0 голосов
/ 28 апреля 2020

Я бы сказал, что вы не можете инициализировать его таким образом, потому что они не совместимы по типу. Ну, если смотреть на строгом уровне ... или на уровне "pedanti c";)

Массив char не равен std :: string, даже если они тесно связаны. Чтобы быть безопасным для типов, компилятор запрещает такие назначения.
Даже массив массивов и char * не идентичны , как объясняют Geeks for Geeks.

Я не вижу здесь ничего бессмысленного .. Может быть, я что-то упустил из виду?

Спецификация c, которую вы опубликовали, в разделе «Заметки» внизу указывает:

В C, массив символов размером на единицу меньше размера строки литерал может быть инициализирован из строкового литерала; результирующий массив не заканчивается нулем. Это не разрешено в C ++.

Я бы сказал, что это объясняет это. Но я согласен, это несколько «скрыто».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...