if constexpr 与 if with constant
if constexpr vs if with constant
如本题所示:,如果两个if
分支都有效,则没有区别:
const int foo = 5;
if (foo == 5)
{
...
}
else
{
...
}
和
const int foo = 5;
if constexpr (foo == 5)
{
...
}
else
{
...
}
在优化方面(在这两种情况下,else
分支都不会被实例化)。因此,如果可以在编译时检查 vanilla if
中的表达式(它涉及 const
或 constexpr
) - 优化也在这里起作用。
我以前以为那是if constexpr
的目的,但我错了。那么是否有 if constexpr
的用例,那么我们可能只有许多 if
分支中的一个有效?
有点人为的例子,但考虑一下:
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
.
的主体
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
与 "optimisation" 有任何关系。这是关于构建阶段的;它是一种工具,有时可以让您在模板元黑客领域强制执行某些操作 "happening"。实际上,这通常意味着编译时执行,但它与 "optimising things out" 没有直接关系,你不应该开始到处散布 if constexpr
只是为了尝试从你的编译中删除 "dead" 分支可执行文件:你的编译器无论如何都会这样做(为什么你的代码中有死分支?)。
如本题所示:if
分支都有效,则没有区别:
const int foo = 5;
if (foo == 5)
{
...
}
else
{
...
}
和
const int foo = 5;
if constexpr (foo == 5)
{
...
}
else
{
...
}
在优化方面(在这两种情况下,else
分支都不会被实例化)。因此,如果可以在编译时检查 vanilla if
中的表达式(它涉及 const
或 constexpr
) - 优化也在这里起作用。
我以前以为那是if constexpr
的目的,但我错了。那么是否有 if constexpr
的用例,那么我们可能只有许多 if
分支中的一个有效?
有点人为的例子,但考虑一下:
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
.
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
与 "optimisation" 有任何关系。这是关于构建阶段的;它是一种工具,有时可以让您在模板元黑客领域强制执行某些操作 "happening"。实际上,这通常意味着编译时执行,但它与 "optimising things out" 没有直接关系,你不应该开始到处散布 if constexpr
只是为了尝试从你的编译中删除 "dead" 分支可执行文件:你的编译器无论如何都会这样做(为什么你的代码中有死分支?)。