【发布时间】:2019-02-06 01:44:03
【问题描述】:
考虑一个对性能非常关键的函数模板func。它可以用T=Type1 或其他类型来实例化。部分函数逻辑依赖于T,它被实例化了。
可以显式使用if constexpr(代码B)或使用原版if(代码A),而编译器可能会优化代码。
但是,我想知道,没有constexpr(代码A)的实现有什么不同?编译器是否能够检测if(在代码A中)的哪个分支在编译时在实例化时使用? 能否(对于代码 A)仍然生成效率较低的代码?
代码 A。没有 if constexpr:
template<class T>
void func(T argument)
{
// some general type-independent logic
if (std::is_same<Type1,T>::value)
{
// do something
}
else
{
// do something else
}
// some general type-independent logic
}
代码 B。与 if constexpr:
template<class T>
void func(T argument)
{
// some general type-independent logic
if constexpr (std::is_same<Type1,T>::value)
{
// do something
}
else
{
// do something else
}
// some general type-independent logic
}
代码 A 和 B 都可以编译,因为 do something 和 do something else 对于任何 T 都是格式正确的。
有一些类似的问题:
-
Why is
constexpr ifneeded? - 当需要constexpr时,此答案会回答。 -
Difference between
ifandconstexpr if– 只列出不同之处
如果出于某种原因代码 B 比代码 A 更可取(当两个分支都格式正确时),上述问题无法回答。
我看到的唯一好处是明确告诉程序员这个if 是编译时的;但是,我会说条件表达式是不言自明的。
【问题讨论】:
-
主要基于意见。对于代码 B 比代码 A“更好”,或者代码 A 比代码 B“更好”,存在争论。这完全取决于对“更好”含义的具体和精确定义。唯一可以客观地说“B”优于“A”的情况是“A”会导致未定义的行为,而“B”不会。其他一切都可以抢夺。
-
使用 B,编译后的代码中将没有分支,所以你已经为你准备好了。这很好。
-
出于同样的原因,
override关键字存在,实际上最好有一个可编译但丢弃的分支,作为金丝雀,如果其他东西在其他一些头文件中发生更改,这将导致丢弃的分支不再编译,并就手头的问题发出警报。 -
@SamVarshavchik
override[contextual] 关键字之所以存在,是因为当您打算覆盖时很容易隐藏签名错误。我不知道您在该评论的其余部分中谈论的是什么好处?请注意,if constexpr的动机很大程度上在于丢弃的分支 不 并且 无法 编译 - 我们正在努力避免这种情况。 -
如果不给出一个长示例,我无法更好地解释这一点,但有时您 /do/ 想要编译错误,如果由于 /not/ 附近的某些更改,上述“紧邻”不再编译,而不是被抑制在
if constexpr中。可以这么说,胶囊总结是避免运行时错误的一种方法是安排(尽可能)将运行时错误转化为编译失败。
标签: c++ c++17 if-constexpr