模板专业化与编译器优化

Ben*_*ler 12 c++ templates

我有一个带有布尔模板参数的类.

template<bool b>
class Foo {
  void doFoo();
};
Run Code Online (Sandbox Code Playgroud)

我想doFoo根据价值做不同的事情b.

天真我能写

选项1

template<bool b> void Foo<b>::doFoo() {
  if (b) cout << "hello";
  else cout << "goodbye";
}
Run Code Online (Sandbox Code Playgroud)

这对我来说似乎效率低下,因为我必须在if每次调用函数时执行一次,尽管在编译时应该知道正确的分支.我可以通过模板专业化解决这个问题:

选项2

template<> void Foo<true>::doFoo() { cout << "hello"; }
template<> void Foo<false>::doFoo() { cout << "goodbye"; }
Run Code Online (Sandbox Code Playgroud)

这样我在运行时就没有执行任何条件.这个解决方案有点复杂(特别是因为在我的实际代码中,类有几个模板参数,你不能部分地专门化函数,所以我需要将函数包装在一个类中).

我的问题是,编译器是否足够聪明,知道不执行条件选项1,因为它总是以相同的方式执行,还是需要编写特化?如果编译器足够智能,我很乐意知道这是依赖于编译器还是我可以依赖的语言功能?

Nat*_*ica 20

编译器可能会优化分支,因为它在编译时已知是什么b.但这并不能保证,唯一可以确定的方法是检查装配.

如果您可以使用C++ 17,则可以使用if constexpr并保证只存在一个分支.

  • 如果具有任何优化标志的编译器没有优化分支,我会提交错误.:) (13认同)
  • @Rakete1111完全.我想这意味着我们需要向MSVS提交一个错误报告,因为它是"大3"中唯一一个编译两个分支而没有优化的报告:https://godbolt.org/g/fgcwqD (4认同)
  • 需要注意的是,这显然在发布模式下进行了优化:https://godbolt.org/g/KZPMgd (3认同)
  • 请注意,如果你想要在`if(b)`branch*上做的事情在`!b`*时会形成错误,那么你将*需要*使用`if constexpr(b)`或将其放入模板特化,防止编译器在`!b`时尝试编译它.如果这不是一个问题(例如,在你的例子中),我个人会坚持使用`if(b)`为了清晰,或者`if constexpr(b)`如果我在一个只有C++ 17的世界.我相信优化器在这里做正确的事情.(其他人的回答和评论提供了经验证据,证明主流优化者确实值得信任.) (2认同)

Use*_*ess 5

这对我来说似乎效率低下,因为每次调用函数时我都必须执行if

编译器可能会对此进行优化 - 但标准并不保证.确切地说,您应该查看您关心的编译器的输出(使用您计划使用的编译选项):例如.clang在链接的示例中没有分支(未优化的版本有很多函数调用样板但没有分支).

在C++ 17中,您可以使用if constexpr,并且未编译的分支将在编译时被丢弃.