如果constexpr vs如果常量

时间:2019-03-29 11:16:36

标签: c++ optimization constexpr if-constexpr

如以下问题所示:link,如果两个if分支都有效,则两者之间没有区别:

const int foo = 5;
if (foo == 5)
{
    ...
}
else 
{
    ...
}

const int foo = 5;
if constexpr (foo == 5)
{
    ...
}
else 
{
    ...
}
关于优化的

(在两种情况下都不会实例化else分支)。因此,如果可以在编译时检查原始if中的表达式(它涉及constconstexpr),那么优化也可以在此处进行。

我以前认为这是if constexpr的目的,但是我错了。那么,除了if constexpr的用例之外,还有很多if分支中只有一个有效吗?

2 个答案:

答案 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只是为了尝试从已编译的可执行文件中删除“死”分支:您的编译器仍然会这样做(为什么您的代码中会有死分支?)。