`if constexpr` 可以用来声明不同类型和 init-expr 的变量吗

Can `if constexpr` be used to declare variables with different types and 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 语言中很常见,但我没有找到有关 C++17 的信息。

当然可以用

std::conditional<..., int, double>::type x;

但仅限于基本情况。即使是不同的初始化器(如上)也会造成大问题。

有两种方法行不通。

首先,变量被限制在它声明的范围内。省略大括号不会骗过编译器:int x = 5 仍然在它自己的范围内,并且在它出现后立即消失。

其次,if constexpr 的宽松语法规则仅适用于 if constexpr 的正文。允许在正文中创建的上下文泄漏到周围的范围是不可行的,因为根据定义它可能格式不正确,或者在 then/else 块之间不一致。 (如果 else 块将 x 声明为类型名怎么办?)

最重要的是,您需要将 bar() 移动到 if-body 或模板 foo() 本身,并让 x 的类型和值由您的 ....

此代码无法运行。问题是当您调用 barx 超出范围。但有一个解决方法:

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

bar(t);

稍微解释一下,它使用即时调用的 lambda 表达式以及自动 return 类型推导。因此,我们在适当的位置赋予 t 值,它不会超出范围。

当然,如果 if 语句不能在编译时求值,它就不会工作。如果你想在这个 lambda 内部做一些运行时操作,你不能将 t 作为 constexpr,但它仍然可以工作。