Разрешить использовать designated initializer из С99

amomum
amomum

Designated initializer - это конструкции такого вида:

struct Person
{  
    int height;
    int weight;
    int age;
};

int main()
{
    Person p = { .age = 18, .height=10, .weight = 5 };
}

Причины за:

  • Это есть в С99
  • Явное указение имен полей, независящее от их порядка - в отличии от допустимого сейчас Person p = {1, 2, 3}
  • Позволит имитировать именованые параметры у функций: foo( (Person){.age = 9, .height=10} );
  • Не нужно писать конструктор для POD-структуры
  • Удобная инициализация массивов структур
  • Уже поддерживается gcc и clang

Причины против:

  • Уже есть конструкторы
  • Неожиданный порядок выполнения кода в инициализаторе (например)
  • Усложнение синтаксиса
  • Неявная инициализация нулем не упомянутых в инициализаторе полей
  • Вероятно, еще что-то

 

22
рейтинг
7 комментариев
Михаил Мальцев
Михаил Мальцев
dix75
Михаил Мальцев,
Да, и уже не раз обсуждалось, хотя и противников не мало.
dix75
zamazan4ik@tut.by
dix75, а не могли бы Вы подсказать, какая аргументация у противников данного предложения?
zamazan4ik@tut.by
yndx-antoshkka
zamazan4ik@tut.by, аргументации против нет. Сейчас предложение крутится в CWG на утверждении формального текста.

В С++20 скорее всего будет.
yndx-antoshkka
Andrey Davydov
zamazan4ik@tut.by, Я вижу 2 сценария контръинтуитивного поведения этой фичи.
--------------------------
Во-первых, это не полностью инициализированный объект (я приводил это пример в комментарии здесь: stdcpp.ru/proposals/d92fe021-6af5-46bd-a520-9ef008cfd2dc) Давайте рассмотрим следующую ситуацию:
struct X
{
int a, b;
};

X x0; // x0.a, x0.b are not initialized
X x1 { 1, 2 }; // x1.a, x1.b are initialized
X x2 {}; // x2.a, x2.b are zero initialized
X x3 { .a = 5 }; // x3.a is initialized, x3.b is not initialized (C99)

Мне не нравится, что x3.b не будет инициализировано, в то время как поля x2 будут.
--------------------------
Во-вторых, порядок вычисления инициализаторов (по мотивам stackoverflow.com/questions/18731707/why-does-c11-not-support-designated-initializer-list-as-c99/29337570?noredirect=1#comment46864214_29337570):
struct Point
{
double lat, lon;
};

double f();
double g();

Point p1 = { f(), g() }; // вызывается f потом g
Point p2 = { .lon = g(), .lat = f() }; // в С99 будет вызываться g а потом f, а как предлагается в C++?
Andrey Davydov
yndx-antoshkka
Andrey Davydov,
Собственно черновик предложения: open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0329r1.pdf

Из него следует, что в первом случае X x3 { .a = 5 }; .b будет проинициализировано 0 (как и в случае с aggregate initialization).

Второй пример не соберётся, т.к. имена полей должны идти в том же порядке, что и при объявлении.

Так что пока выглядит весьма предсказуемо, но не так функционально как хотелось бы.
yndx-antoshkka
Andrey Davydov
yndx-antoshkka,
> Собственно черновик предложения: open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0329r1.pdf
Спасибо за пояснение, я весь proposal читать поленился.
> Из него следует, что в первом случае X x3 { .a = 5 }; .b будет проинициализировано 0 (как и в случае с aggregate initialization).
Логично с точки зрения C++ но отличается от C. Это ведь проблема(?)
> Второй пример не соберётся, т.к. имена полей должны идти в том же порядке, что и при объявлении.
>
> Так что пока выглядит весьма предсказуемо, но не так функционально как хотелось бы.
Это урезает "половину полезности" designated initializers. Читать такой код
Point p = { .lat = f(), .lon = g(), };
приятнее, чем такой
Point p = { f(), g() };
но при написании все равно приходится помнить, что lat объявлено раньше lon.
Andrey Davydov
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).