Почему синтаксис двойных фигурных скобок не предпочтителен для конструкторов, принимающих std :: initializer_list
Равномерная инициализация является важной и полезной функцией C ++ 11. Тем не менее, вы не можете просто использовать{}
с тех пор
std::vector<int> a(10, 0); // 10 elements of value zero
std::vector<int> b({10, 0}); // 2 elements of value 10 and 0 respectively
std::vector<int> c{10, 0}; // 2 elements of value 10 and 0 respectively
std::vector<int> d = {10, 0}; // 2 elements of value 10 and 0 respectively
auto e(0); // deduced type is int
auto f = 0; // deduced type is int
auto g{0}; // deduced type is std::initializer_list<int>
auto h = {0}; // deduced type is std::initializer_list<int>
Отмечая чтоагрегатная инициализация например,std::arrays
требует использования{{}}
мне кажется, что вся проблема скакой векторный конструктор будет выбран можно было бы избежать, потребовав{{}}
вызывать конструкторов, принимающихstd::initializer_list
:
std::vector<int> i{10, 0}; // 10 elements of value zero
std::vector<int> j{{10, 0}}; // 2 elements of value 10 and 0 respectively
std::vector<int> k = {10, 0}; // 2 elements of value 10 and 0 respectively
auto l{0}; // deduced type is int
auto m{{0}}; // deduced type is std::initializer_list<int>
auto n = {0}; // deduced type is std::initializer_list<int>
Я уверен, что это обсуждалось, так каковы были причины против этого? Цитата / ссылка из стандартного предложения предпочтительнее в качестве ответа.
Обновить. - Есть смысл вN2532 что говорится:
(3) Вероятные неприятные случаи неоднозначности происходят только для коротких списков инициализаторов [...]
(5) Почему языковые правила должны заставлять программистов, которые хотят, чтобы краткость и контроль неоднозначности (по вполне веским причинам) писали больше, чтобы угодить программистам, которые предпочитают (по совершенно веским причинам) быть более явными - и может быть?
[...]
Предположим, что программист ожидает вызова функции f (X). Как f (Y) может «перехватить» звонок?
(4) Предположим, что X не имеет конструктора списка инициализаторов, а Y имеет. В этом случае приоритет, отданный конструкторам списка инициализаторов, отдает предпочтение угонщику (помните, мы предполагали, что программист каким-то образом ожидал вызова функции f (X)). Это аналогично тому, что кто-то ожидает, что f (y) вызовет f (X), используя пользовательское преобразование, и кто-то придет с f (Y), который точно совпадает.Я думаю, было бы справедливо ожидать, что кто-то, кто использует {…}, вспомнит о возможности конструкторов списков инициализаторов. [Акцент мой]
Я думаю, ключ кроется вможет бытьЭто означает, что вам не нужно использовать одинаковую инициализацию. С помощью{}
правильно трудно, так как:
Вы должны не только проверить конструктор, который вы хотите вызвать, но и длялюбой конструктор принимаетinitializer_list
это может победить (и, вероятно, будет) над этим;
если вы пишете код, используя{}
и кто-то в будущем добавляетstd::initializer_list
конструктор ваш код может сломаться и сделать этомолча.
Даже если у вас есть классA
с конструкторамиA(int, bool)
а такжеA(std::initializer_list<double>)
, последний будет выбран над первым дляA a{0, false};
(что IMO сумасшедший), так что я нахожу этодействительно трудно использовать равномерную инициализацию для классов, которые имеют илиможет быть есть (требуется сверхдержава хрустального шара)initializer_list
Конструкторы.
Тот факт, что ваш код может молча взломать меня очень беспокоит.