Может ли `if constexpr` использоваться для объявления переменных разных типов и init-expr

Например:

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;

но только в элементарных случаях. Даже разные инициализаторы (как указано выше) создают большие проблемы.

6

Решение

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

constexpr auto t = []() -> auto {
if constexpr(/* condition */) return 1;
else return 2.9;
}();

bar(t);

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

Конечно, это не сработало бы, если бы оператор if не мог быть оценен во время компиляции. И если вы хотите выполнить некоторые операции во время выполнения этой лямбды, вы не можете использовать t как constexpr, но он все равно будет работать.

7

Другие решения

Есть два способа, которыми это не сработает.

Во-первых, переменная ограничена областью, в которой она объявлена. Выход из скобок не обманет компилятор: int x = 5 все еще в своей области видимости и исчезает сразу после его появления.

Во-вторых, смягченные грамматические правила для if constexpr применяются только в if constexprтело Было бы невозможно допустить, чтобы контекст, созданный в теле, просочился в окружающую область, так как по определению он может быть не правильно сформирован или согласован между блоком then / else. (Что делать, если объявлен блок else x как имя типа?)

Итог, вам нужно двигаться bar() в if-body или шаблон foo() сам и имеет тип и значение x определяется вашим ...,

2

По вопросам рекламы [email protected]