cpp-ru/ideas

Расширение designated initialization для заполнения отдельных полей полей.

Opened this issue · 1 comments

Предложение

Предположим, у нас есть структура B, которая содержит поле типа A:

struct A { int x; int y; };
struct B {
  A a;
  int z;
}

Сейчас, если я хочу использовать designated initialization для объекта типа B, мне нужно расписать поле a отдельно:

B b = B{
  .a = A{
    .x = 123
  },
  .z = 3
}

Из-за этого появляется некоторая лишня вложенность.

Предлагается поддержать C-style подход. где в designated initialization можно использовать вложенные поля:

B b = B{
  .a.x = 123,
  .z = 3
}

Подразумевается, что код выше является синтаксическим сахаром для работающего варианта. Все незадействованные поля заполняются аналогично текущей реализации с zero initialisation.

Где может быть полезно

В небезызвестном фреймворке userver (по крайней мере внутри) при собирании реквеста для похода в эндпоинт другого сервиса часто приходится делать что-то такое:

Request request;
request.auth_context = auth_context;
request.body = Request::Body {
  .field = value1,
  .val = value2
};

или такого:

Request request{
  .auth_context = auth_context,
  .body = Request::Body{
    .field = value1,
    .val = value2
  }
};

Хотя можно обойтись таким:

Request request{
  .auth_context = auth_context,
  .body.field = value1,
  .body.value = value2
};

Если поле - композиция, то странно, что там только один элемент композиции инициализируется. Скорей всего это значит что у нас какой-то частный случай. Чаще требуется инициализировать несколько полей структуры и синтаксис с фигурными скобками не является избыточным в таком случае:

    vk::ImageCreateInfo imageCreateInfo = {
        .flags = {},
        .imageType = vk::ImageType::e2D,
        .format = format,
        .extent = {
            .width = size.width,
            .height = size.height,
            .depth = 1,
        },
        .mipLevels = 1,
        .arrayLayers = 1,
        .samples = vk::SampleCountFlagBits::e1,
        .tiling = vk::ImageTiling::eOptimal,
        .usage = imageUsage,
        .sharingMode = vk::SharingMode::eExclusive,
        .initialLayout = vk::ImageLayout::eUndefined,
    };
    imageCreateInfo.setQueueFamilyIndices(queueFamilyIndex);