Например:
void foo()
{
if constexpr (...)
int x = 5;
else
double x = 10.0;
bar(x); // calls different overloads of bar with different values
}
Это распространенный случай в D lang, но я не нашел информации о C ++ 17.
Конечно, можно использовать что-то вроде
std::conditional<..., int, double>::type x;
но только в элементарных случаях. Даже разные инициализаторы (как указано выше) создают большие проблемы.
Нет никакого способа, которым этот код мог бы работать. Проблема в том, что x
вне зоны действия при звонке bar
, Но есть обходной путь:
constexpr auto t = []() -> auto {
if constexpr(/* condition */) return 1;
else return 2.9;
}();
bar(t);
Чтобы объяснить немного, он использует мгновенно вызванное лямбда-выражение вместе с автоматическим возвращением типа возврата. Поэтому мы даем т значение на месте, и оно не выходит за рамки.
Конечно, это не сработало бы, если бы оператор if не мог быть оценен во время компиляции. И если вы хотите выполнить некоторые операции во время выполнения этой лямбды, вы не можете использовать t как constexpr, но он все равно будет работать.
Есть два способа, которыми это не сработает.
Во-первых, переменная ограничена областью, в которой она объявлена. Выход из скобок не обманет компилятор: int x = 5
все еще в своей области видимости и исчезает сразу после его появления.
Во-вторых, смягченные грамматические правила для if constexpr
применяются только в if constexpr
тело Было бы невозможно допустить, чтобы контекст, созданный в теле, просочился в окружающую область, так как по определению он может быть не правильно сформирован или согласован между блоком then / else. (Что делать, если объявлен блок else x
как имя типа?)
Итог, вам нужно двигаться bar()
в if-body или шаблон foo()
сам и имеет тип и значение x
определяется вашим ...
,