【问题标题】:Can `if constexpr` be used to declare variables with different types and init-expr`if constexpr` 能否用于声明不同类型的变量和init-expr
【发布时间】:2018-01-23 08:43:19
【问题描述】:

例如:

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;

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

【问题讨论】:

  • 不,由于范围界定,这是不可能的。而是调用ifelse 中的函数。可能还有其他解决方案,但在不确切知道这应该解决什么问题、用例的情况下,目前真的不可能多说。
  • 在调用bar() 时,您的变量都不存在。你的问题只是不恰当的,与constexpr无关。
  • “调用内部函数” - 这意味着所有代码的重复,并可能与多个 if 表达式组合爆炸。如果分支没有作用域,则在 D 中为静态。如果真的需要范围,您仍然可以添加额外的 {}。
  • @aaalex88:重载解析不能动态发生;为bar(x) 选择的函数必须在编译时已知。
  • @AndyG 它没有:if 是 constexpr,所以 x 的类型在编译时是已知的

标签: c++ metaprogramming c++17 if-constexpr


【解决方案1】:

这段代码不可能工作。问题是当您调用barx 超出范围。但是有一个解决方法:

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

bar(t);

稍微解释一下,它使用即时调用的 lambda 表达式以及自动返回类型推导。因此,我们将 t 值赋予到位,并且它不会超出范围。

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

【讨论】:

  • 感谢 Dev Null 纠正了我代码中的一些语法错误。对不起他们,写得有点粗心,只是为了得到一个想法。
  • 是的,它在很多情况下都非常有用。我是否正确可以制作auto t = [&amp;]() -&gt; auto { .../*some code, depend on runtime function params, but still with constexpr if statement*/... }
  • @aaalex 没有。我已经测试过了。它根本不能依赖运行时参数。如果是这样,编译器将抱怨它无法评估 constexpr,如果或者如果您删除了 constexpr,它将无法评估 auto。所以在这种情况下没有运行时条件。如果你用 t const 代替 constexpr,它可以在运行时计算值,但返回类型必须在编译时明确。
  • @aaalex88 你绝对可以做类似[](int x) -&gt; auto { if constexpr(/* condition */) return sqrt(x); else return x; }(someRuntimeInt);基本上,/* condition */ 中的部分需要是constexpr,而分支中的实际代码可以是运行时
【解决方案2】:

有两种方法不起作用。

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

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

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

【讨论】:

  • "如果 else 块将 x 声明为类型名怎么办?" - 当然,程序格式不正确。上面已经说过:如果我们有几个静态条件,它们需要具有相同代码的指数数量的分支,因此移动 bar 并不是最好的解决方案。同样在 D static if 中只是没有创建范围,所以这是语言设计的失败。
  • 不要将constexpr if 误认为static if。两者有完全不同的目标:一个有条件地启用一个块,另一个有条件地启用注入周围块的多行代码。如果您想提议 static if 作为 C++ 的一项功能,可以在 open-std.org/jtc1/sc22/wg21 找到工作组。
  • 别打扰了。 D风格static if首先被提出。它着火了。
  • @aaalex88 D 的静态 if 不是故意创建范围。静态 if/else 是一种代码生成结构,就像静态 foreach 一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-23
  • 1970-01-01
  • 1970-01-01
  • 2015-03-09
相关资源
最近更新 更多