【问题标题】:May a compiler elide the evaluation of the "not-taken" branch in a constexpr function?编译器可以忽略对 constexpr 函数中“未采用”分支的评估吗?
【发布时间】:2012-12-22 05:35:53
【问题描述】:

在尝试回答 question by Mehrdad 时,我编写了下面的小函数(在 liveworkspace 上运行):

template <typename T, unsigned low, unsigned high>
static constexpr auto highest_index_in() ->
   typename std::enable_if<high >= low, unsigned>::type
{
   return low == high                 ? low :
          high == low + 1             ? (exists<T, high>() ? high : low) :
          exists<T, (high + low)/2>() ? highest_index_in<T, (high+low)/2, high>() :
                                        highest_index_in<T, low, (high+low)/2>();
} // highest_index_in

(其中exists 为 O(1))

尽管编译非常慢(在 liveworkspace 上),并且尝试使用宽范围完全失败并导致编译器崩溃([0, ~0u] 不起作用...)。

我相信我设法正确地实现了递归(我很高兴被反驳),但是......

因此问题是:在此处评估各种三元运算符调用时,编译器是否可以省略未采用分支的计算?

【问题讨论】:

  • 不,所有条件分支都必须被计算,constexpr 没有帮助,因为它可以作为普通函数执行。
  • @Xeo:这是我的观点,当评估为正常功能时,只执行一个分支! .... 我突然意识到,即使没有执行计算,也可能需要实际实例化函数模板。
  • @MatthieuM.: 是的,有必要实例化它,编译器不能只是试图弄清楚代码在未采用的分支中的含义。
  • 这就是为什么人们要求一个静态的 if,它只会实例化一个分支。
  • 如果不实际实例化死代码,编译器必须至少做足够的工作来确定它可以实例化它。否则,它可能无法提供所需的诊断。据推测,如果编译器足够聪明,可以确定它可以实例化它,但是这样做之后它可以删除它,那么将允许不实例化它(“as-if” )。我怀疑编译器必须证明递归是有根据的才能做到这一点,或者至少它不会遇到任何需要诊断的“坏”情况。

标签: c++ c++11 ternary-operator language-lawyer constexpr


【解决方案1】:

不,编译器不能跳过对三元运算符未采用分支的评估,因为这样做意味着编译器首先必须确定在任何可能的分支中没有冲突的重载和/或模板特化这可能会使程序格式错误。为此,编译器必须有效地实例化分支上使用的模板并对函数执行重载决策。

【讨论】:

  • 是的,刚刚意识到......它可以避免计算值但必须实例化(递归)函数体。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-27
  • 1970-01-01
  • 2021-02-13
  • 1970-01-01
  • 2012-12-24
  • 2014-04-06
  • 2022-11-18
相关资源
最近更新 更多