Почему C++ не допускает неявную инициализацию списка в условном операторе?

Этот код компилируется:

std::string f(bool a, std::string const& b)
{
    if (a) return b;
    return {};
}

Этот код также компилируется:

std::string f(bool a, std::string const& b)
{
    return a ? b : std::string{};
}

Этот код не компилируется:

std::string f(bool a, std::string const& b)
{
    return a ? b : {};
}

Учитывая, что оба результирующих значения оператора ?: должны быть одного типа, почему он не выводит тип, как в первом примере?


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


person Miral    schedule 15.05.2019    source источник
comment
Оба типа должны быть преобразованы в один и тот же тип. {} не имеет типа.   -  person NathanOliver    schedule 15.05.2019
comment
clang говорит, что {} — это список инициализаторов (который здесь нельзя использовать) live: godbolt.org/z/imYL6q   -  person Richard Critten    schedule 15.05.2019
comment
Замена {} на std::initializer_list<char>() также компилируется.   -  person jcai    schedule 15.05.2019
comment
Возможно, этот вопрос можно было бы превратить в языковое предложение   -  person M.M    schedule 15.05.2019
comment
@miral: правильный термин - инициализация списка. Так это называется в стандарте; вы ничего не найдете в стандарте о унифицированной инициализации.   -  person Nicol Bolas    schedule 15.05.2019


Ответы (1)


Инициализатор в фигурных скобках не является выражением и, следовательно, не имеет типа. Видеть:

https://scottmeyers.blogspot.com/2014/03/if-braced-initializers-have-no-type-why.html

Инициализатор в фигурных скобках — это грамматическая конструкция со специальными стандартными правилами, явно определяющими разрешенное использование и вывод типа. Эти специальные правила нужны именно потому, что инициализаторы в фигурных скобках не имеют типа. Использование их в операторах ?: не указано, поэтому программа имеет неправильный формат.

Если вам действительно нужно услышать, как сам человек скажет это три раза подряд, прежде чем вы в это поверите, то:

https://youtu.be/wQxj20X-tIU?t=1792

person Nikos C.    schedule 15.05.2019
comment
но return {}; работает - person xaxxon; 15.05.2019
comment
@xaxxon С return {} известен возвращаемый тип функции. - person Nikos C.; 15.05.2019
comment
с return a ? b : {}; тип возвращаемого значения функции неизвестен? - person xaxxon; 15.05.2019
comment
@xaxxon Тип возвращаемого значения известен, но тип ?: неизвестен. - person Nikos C.; 15.05.2019
comment
return a ? b : ""; компилируется, как и return a ? b : std::initializer_list<char>{};. Таким образом, компилятору разрешено выполнять построение/преобразование на основе объявленного возвращаемого типа и/или типа b. Таким образом, {} должно быть одинаково действительным. - person Miral; 15.05.2019
comment
@Miral "" имеет тип. std::initializer_list<char>{} также имеет тип. {} нет. - person Nikos C.; 15.05.2019
comment
Правильно, но это означает, что он совместим с любым типом, и именно так он работает в операторах возврата, аргументах и ​​инициализации для начала. - person Miral; 15.05.2019
comment
@Miral: он совместим с любым типом Нет, это не так. Это грамматическая конструкция, которая в определенных местах может использоваться для инициализации значения типа. Он ни с чем не совместим. - person Nicol Bolas; 15.05.2019
comment
@Miral Это потому, что стандарт специально разрешает это. Инициализаторы в фигурных скобках не имеют типа, поэтому их разрешенное использование должно быть явно указано в стандарте. Использование его в ?: никогда не указывалось, поэтому программа имеет неправильный формат. - person Nikos C.; 15.05.2019
comment
@NikosC.: Следует отметить, что списки инициализации в фигурных скобках не имеют типа, потому что они не являются выражениями. Они представляют собой отдельную грамматическую конструкцию от выражений. Поэтому спрашивать их о типе — все равно, что спрашивать их об их значении или о чем-то другом, связанном с выражениями. - person Nicol Bolas; 15.05.2019
comment
@xaxx в спецификации языка для оператора return прямо говорится, что следующим может быть либо выражение, либо список в фигурных скобках, и далее определяется, что произойдет, если будет предоставлен список в скобках (а именно, что список в скобках принимается как инициализатор для копирования-инициализации объекта результата) - person M.M; 15.05.2019
comment
Я понимаю, что это не ошибка компилятора. Но другой способ интерпретировать вопрос: действительно ли это имеет смысл как требование? или есть техническая причина, по которой это невозможно сделать? - person xaxxon; 15.05.2019
comment
Как заявил модератор, кажется, что на этот вопрос может быть ответ, аналогичный этому (который, по сути, сводится к тому, что никто не думал об этом при написании спецификации языка). Я не понимаю, как это дублируется. И я не вижу причин, по которым это невозможно сделать, так как тип можно угадать по одному из операндов. - person rAndom69; 15.05.2019