Фикс баги с инициализацией инта
В
прошлом посте говорили об одной неприятности при использовании универсальной инициализации интов. При таком написании:
auto i = {0};
i будет иметь тип std::initializer_list<int>.
С++17 исправил такое поведение. Но для полного понимания мы должны определить два способа инициализации: копирующая и прямая. Приведу примеры
auto x = foo(); // копирующая инициализация
auto x{foo()}; // прямая инициализация,
// проинициализирует initializer_list (до C++17)
int x = foo(); // копирующая инициализация
int x{foo()}; // прямая инициализация
Для прямой инициализации вводятся следующие правила:
• Если внутри скобок 1 элемент, то тип инициализируемого объекта - тип объекта в скобках.
• Если внутри скобок больше одного элемента, то тип инициализируемого объекта просто не может быть выведен.
Примеры:
auto x1 = { 1, 2 }; // decltype(x1) - std::initializer_list<int>
auto x2 = { 1, 2.0 }; // ошибка: тип не может быть выведен,
// потому что внутри скобок объекты разных типов
auto x3{ 1, 2 }; // ошибка: не один элемент в скобках
auto x4 = { 3 }; // decltype(x4) - std::initializer_list<int>
auto x5{ 3 }; // decltype(x5) - int
Этот фикс компиляторы реализовали задолго до того, как стандарт с++17 был окончательно утвержден. Поэтому даже с флагом -std=c++11 вы можете не увидеть некорректное поведение. Оно воспроизводится только на древних версиях. Можете убедиться
тут.
Fix your flaws. Stay cool.
#cpp11 #cpp17 #compiler