std::string(count, ch) не вызывается при использовании юниформ-инициализации

Меня только что поймала эта, казалось бы, невинная попытка вызвать конструктор std::string который принимает размер и символьное значение, используя унифицированный синтаксис инициализации:

std::string s{ 10, '\0' };

Я думал, что это создаст строку длиной 10, инициализированную \0.

Хотя на самом деле он вызывает конструктор, который принимает список инициализаторов и, таким образом, создает строку длиной 2, инициализированную {'\n', '\0'}!

См. демонстрацию на Coliru.

Есть ли способ избежать этой ловушки при использовании юниформ-инициализации? Или мне просто нужно быть осторожным?

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


person zett42    schedule 10.05.2017    source источник
comment
Я думаю, что запись в Википедии об униформной инициализации хорошо описывает это: Единая инициализация не заменяет синтаксис конструктора, который иногда все еще необходим. Если класс имеет конструктор списка инициализаторов (TypeName(initializer_list<SomeType>);), то он имеет приоритет над другими формами построения при условии, что список инициализаторов соответствует типу конструктора последовательности.   -  person clcto    schedule 11.05.2017
comment
Компилятор @clcto, похоже, стремится использовать конструктор списка инициализаторов, даже если список состоит из несоответствующих типов (Пример Колиру). Честно говоря, есть предупреждение компилятора.   -  person zett42    schedule 11.05.2017
comment
@ zett42: Для справки, такое поведение гарантируется [over.match.list]/1; в принципе; конструкторы просматриваются в два этапа, и если какие-либо конструкторы списка инициализаторов вообще существуют, то это то, что вы получаете, к лучшему или к худшему.   -  person Lightness Races in Orbit    schedule 11.05.2017


Ответы (1)


Вы просто должны быть осторожны.

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

Кроме того, игнорируйте название функции.

xkcd #927: Стандарты

person Lightness Races in Orbit    schedule 10.05.2017
comment
Что ж, эта функция официально не называется униформной инициализацией в стандарте (или единорогом, если уж на то пошло). - person T.C.; 11.05.2017
comment
Честно говоря, инициализация списка должна работать таким образом. Он мог включить в себя все формы инициализации, если бы комитет не допустил две ошибки: отдал предпочтение initializer_list конструкторам и запретил сужающие преобразования. Удалите оба из них, и вы сможете законно заменить любой случай инициализации () на {}. - person Nicol Bolas; 11.05.2017