考虑一个函数模板func
这是非常关键的性能。它可以与T=Type1
或一些其他类型的实例化。功能逻辑的一部分取决于T
它与实例化。
一个可以显式使用if constexpr
(代码B)或使用香草if
代替(代码A),而编译器可能优化代码。
不过,我不知道,没有constexpr
(代号A)如何实施是有什么不同?是不是编译器能够检测在编译时间,而实例化使用哪个if
(以代码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
。
还有一些发音相似的问题:
constexpr if
needed? - 在需要的时候constexpr
这一个答案。if
and constexpr if
- 仅列出差异(当两个分支是无论如何也形成)。上述的问题不回答,如果代码B是最好代码A出于某种原因。
我看到的唯一好处是明确地告诉程序员,这是if
编译时;但是,我要说的条件表达式是不言自明。
if constexpr
无意有关优化。编译器在优化掉一个分支,是if (true)
或if (false)
非常好(因为我们谈论的常量表达式,这是它归结为)。这里是OP的例子的godbolt demo - 你会注意到,GCC和铿锵,甚至-O0
,不发出分支的简单if
。
if constexpr
是所有关于确保只有一个if
的分支被实例化。这是非常重要的,有价值的写作模板 - 因为现在我们其实可以写有条件编译相同功能的体内代码,而不是写多个人工功能,只是为了避免实例化。
也就是说,如果你有一个条件,即是一个已知常量表达式 - 只是一直用if constexpr
,你是否不需要实例化的好处。没有缺点这样的决定。这使得它更清晰,以飨读者,确实这个条件不变(因为否则它甚至不会编译)。这也将迫使表达的评价作为常数(slight variant导致海湾合作委员会发出的-O0
一个分支,以为不-O1
),这与即将到来的除了is_constant_evaluated()
可能成为从长远来看更重要(甚至可能是否定我的首段)。
我看到的唯一好处是明确地告诉程序员,这是否编译时间;但是,我要说的条件表达式是不言自明。
要明确解决这个问题,是的,std::is_same<X, Y>::value
是“不言自明”,这是一个常数表达式...因为我们恰好是熟悉std::is_same
。但它不太明显foo<X>::value
是否是一个常量表达式,或者是否foo<X>() + bar<Y>()
是一个常量表达式或任何以上任意复杂的比。
它看到if constexpr
,使事实,这是编译时不言自明的,而不是病情本身的内容。