Наивный, оптимистичный и oh.. так неправильный взгляд на синтаксис синтаксиса С++ 11
Я думал, что поскольку С++ 11 пользовательские объекты типа должны быть построены с помощью нового синтаксиса {...}
вместо старого синтаксиса (...)
(за исключением перегруженного конструктора для std::initializer_list
и аналогичных параметров (например, std::vector
: размер ctor vs 1 elem init_list ctor)).
Преимущества: отсутствие узких неявных преобразований, отсутствие проблем с наиболее неприятным анализом, согласованность (?). Я не видел проблем, поскольку я думал, что они одинаковые (кроме приведенного примера).
Но это не так.
Рассказ о безумном безумии
{}
вызывает конструктор по умолчанию.
... За исключением случаев, когда:
- конструктор по умолчанию удаляется и
- других конструкторов не определено.
Тогда похоже, что это скорее значение инициализирует объект?... Даже если объект удалил конструктор по умолчанию, {}
может создать объект. Разве это не превзошло всю цель удаленного конструктора?
... За исключением случаев, когда:
- объект имеет удаленный конструктор по умолчанию и
- определены другие конструкторы.
Затем он терпит неудачу с call to deleted constructor
.
... За исключением случаев, когда:
- объект имеет удаленный конструктор и
- никакой другой конструктор не определен и
- как минимум нестатический элемент данных.
Затем он не работает с отсутствующими инициализаторами поля.
Но тогда вы можете использовать {value}
для создания объекта.
Хорошо, возможно, это то же самое, что и первое исключение (значение init объект)
... За исключением случаев, когда:
- класс имеет удаленный конструктор
- и по крайней мере один элемент данных в классе по умолчанию инициализирован.
Тогда ни {}
, ни {value}
не могут создать объект.
Я уверен, что пропустил несколько. Ирония заключается в том, что он называется равномерным синтаксисом инициализации. Я снова говорю: синтаксис инициализации UNIFORM.
Что это за безумие?
Сценарий A
Удаленный конструктор по умолчанию:
struct foo {
foo() = delete;
};
// All bellow OK (no errors, no warnings)
foo f = foo{};
foo f = {};
foo f{}; // will use only this from now on.
Сценарий B
Удаленный конструктор по умолчанию, остальные конструкторы удалены
struct foo {
foo() = delete;
foo(int) = delete;
};
foo f{}; // OK
Сценарий C
Удаленный конструктор по умолчанию, другие конструкторы, определенные
struct foo {
foo() = delete;
foo(int) {};
};
foo f{}; // error call to deleted constructor
Сценарий D
Удаленный конструктор по умолчанию, другие конструкторы не определены, член данных
struct foo {
int a;
foo() = delete;
};
foo f{}; // error use of deleted function foo::foo()
foo f{3}; // OK
Сценарий E
Удаленный конструктор по умолчанию, удаленный конструктор T, член данных T
struct foo {
int a;
foo() = delete;
foo(int) = delete;
};
foo f{}; // ERROR: missing initializer
foo f{3}; // OK
Сценарий F
Удаленный конструктор по умолчанию, инициализаторы элементов данных класса
struct foo {
int a = 3;
foo() = delete;
};
/* Fa */ foo f{}; // ERROR: use of deleted function `foo::foo()`
/* Fb */ foo f{3}; // ERROR: no matching function to call `foo::foo(init list)`