【问题标题】:How do I force the compiler to evaluate a switch at compile time?如何强制编译器在编译时评估开关?
【发布时间】:2020-08-22 10:15:11
【问题描述】:

我正在开发一个嵌入式项目(只有 C++14 编译器可用),我想优化执行速度。

这是我正在做的一个例子。

enum gpio_type{
  TYPE_1,
  TYPE_2
}

template <gpio_type T>
class test{
  test(){}

  void set_gpio(bool output)
  {
    switch (T)
    {
      case TYPE_1:
        do_something();
        break;

      case TYPE_2:
        do_something_else();
        break;
    }
  }
}

编译器会在编译时自动删除死代码吗?如果是这样,它是标准功能还是依赖于编译器?如果没有,是否可以以强制优化的方式编写代码?

【问题讨论】:

  • 为什么不将set_gpio 专门用于不同的枚举值?

标签: c++ c++14


【解决方案1】:

您可以专门针对不同的枚举值 set_gpio - 例如。 :

template <gpio_type T>
class test{
  public:
    test(){}

    void set_gpio(bool output);
};

template<> void test<TYPE_1>::set_gpio(bool output) {
  do_something();
}

template<> void test<TYPE_2>::set_gpio(bool output) {
  do_something_else();
}

正如其他答案所表明的那样,如果您的编译器在优化方面接近体面,您可能不需要这样做。但是上面的内容可能更易读。

【讨论】:

    【解决方案2】:

    恒定传播和死代码消除是最简单的编译器优化之一。由于T 是一个编译时间常数,如果代码没有经过任何编译器优化,我会感到非常惊讶。

    我有 tested 15 compilers and platforms on godbolt 从古老的 x86 到 arm、avr、risc-v、raspberry 和 arduino(以及更多)。所有这些都只是编译为相当于尾调用跳转。没有测试,没有条件跳转。自己去看看吧。

    在这一点上,我可以相当有信心地说,没有性能原因来修改您的代码。

    【讨论】:

    • 很好,这是测试各种代码优化的好方法!谢谢
    【解决方案3】:

    这可能取决于您是否启用优化以及您的编译器的智能程度。我猜当前的编译器会在这种情况下进行优化,至少如果它们内联函数的话。

    但如果你想 100% 确定

    • 为不同的枚举值专门化模板或
    • 使用您的开关并查看编译器的汇编器输出,以检查编译器是否按照您的要求进行了优化或
    • 使用 C++17 和if constexpr

    【讨论】:

      【解决方案4】:

      我会将仿函数(do_something 或 do_something_else)作为模板参数传递。

      这样,你set_gpio的代码就更清晰了,你肯定有一个编译时间推演了哪个函数。

      在这篇文章中,您可以看到这是如何完成的: Function passed as template argument

      【讨论】:

        猜你喜欢
        • 2012-02-01
        • 1970-01-01
        • 2012-12-26
        • 2011-09-27
        • 2017-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多