3

如这个问题所示:link,如果两个if分支都有效,则没有区别:

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

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

在优化方面(在这两种情况下,else分支都不会被实例化)。if因此,如果可以在编译时检查vanilla 中的表达式(它涉及 a constor constexpr) - 优化也可以在这里工作。

我以前认为这是 的目的if constexpr,但我错了。那么除了案例之外是否还有其他用例,if constexpr那么我们可能只有许多if分支中的一个有效?

4

2 回答 2

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.

于 2019-03-29T11:27:07.290 回答
7

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);
   }
}

…断言仍然会触发;你的程序格式不正确。想出一个真实世界的例子来说明你什么时候会受到打击并不一定容易,但这仍然可以说是出乎意料的。

一般来说,尽量不要认为constexpr与“优化”有任何关系。这是关于构建阶段;它是一种工具,有时可以让您强制执行模板 metahackerer 领域中“发生”的一些事情。在实践中,这通常意味着编译时执行,但它与“优化事物”没有直接关系,而且你不应该开始if constexpr到处撒泼,只是试图从编译的可执行文件中删除“死”分支:你的编译器正在这样做无论如何(为什么你的代码中有死分支?)。

于 2019-03-29T11:43:52.450 回答