如以下问题所示:link,如果两个if
分支都有效,则两者之间没有区别:
const int foo = 5;
if (foo == 5)
{
...
}
else
{
...
}
和
const int foo = 5;
if constexpr (foo == 5)
{
...
}
else
{
...
}
关于优化的(在两种情况下都不会实例化else
分支)。因此,如果可以在编译时检查原始if
中的表达式(它涉及const
或constexpr
),那么优化也可以在此处进行。
我以前认为这是if constexpr
的目的,但是我错了。那么,除了if constexpr
的用例之外,还有很多if
分支中只有一个有效吗?
答案 0 :(得分:7)
一个人为的例子,但是考虑一下:
const int foo = 6;
if (foo == 5)
{
some_template_that_fails_to_compile_for_anything_else_than_5<foo>();
}
即使永远不会执行if
的正文,也不会编译!编译器仍然必须发出错误。另一方面,这
const int foo = 6;
if constexpr (foo == 5)
{
some_template_that_fails_to_compile_for_anything_else_than_5<foo>();
}
很好,因为编译器在编译时就知道foo
的值,因此不会打扰if
的主体。
答案 1 :(得分:6)
if constexpr
在这方面有点令人困惑。
不能确保无法访问的分支得到优化(通常会发生这种情况)。
如果编译错误取决于模板参数,可以让我们编写可能无法编译的代码而不会破坏构建。都是关于模板实例化的。
所以:
template <typename T>
void foo(T x)
{
if constexpr (std::is_same_v<T, int>)
{
// Code that's semantically invalid for non-int can go here!
// Naive example (though obviously this works with some non-int types too)
x += 42;
}
}
不幸的是,这不会扩展到不依赖T的条件,因此,如果您想这样做:
constexpr bool DoThings = false;
void foo()
{
if constexpr (DoThings)
{
static_assert(false);
}
}
…断言仍然会触发; your program is ill-formed。提出一个现实世界中的例子不一定很容易,但是仍然可以说是出乎意料的。
通常,请尽量不要将constexpr
视为与“优化”有关。它是关于构建阶段的;它是一个有时使您在模板metahackerer领域中强制某些事情“发生”的工具。实际上,这通常意味着编译时执行,但这与“优化事情”没有直接关系,并且您不应开始在各处撒满if constexpr
只是为了尝试从已编译的可执行文件中删除“死”分支:您的编译器仍然会这样做(为什么您的代码中会有死分支?)。