"if constexpr" 在模板之外有用吗?
Is "if constexpr" useful outside of templates?
我正在尝试完全理解 if constexpr
。
我明白,如果if constexpr(expr)
在模板中使用,并且expr
依赖于模板参数,那么在实例化过程中,只有then
/[=15之一=] 分支会被实例化,其他的会被丢弃。
我有两个问题:
- 如果
expr
不依赖于模板参数,那么 if constexpr(expr)
的任何分支都不会被丢弃,这是真的吗?如果是,标准在哪里这样说?我看不出标准在哪里有例外,只有当 expr
依赖时才会发生丢弃。
if constexpr
在模板之外有用吗?如果是,这有哪些用例?你能举一些例子来理解它的用处吗?
Is it true, that if expr
is not dependent on a template parameter, then no branches of if constexpr(expr)
will be discarded? If yes, where does the standard say so? […]
是的,确实如此。您正在寻找 [stmt.if]/2。具体这部分:
[…] During the instantiation of an enclosing templated entity, if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated. […]
我能找到的最好的例子是 cppreference.com:
template<class T> void g() {
auto lm = [](auto p) {
if constexpr (sizeof(T) == 1 && sizeof p == 1) {
// this condition remains value-dependent after instantiation of g<T>
}
};
}
Is if constexpr
useful outside of templates? If yes, can you give some examples to understand its usefulness?
虽然当 if constexpr
没有出现在模板内部时所有分支都将被实例化,但 [basic.def.odr]/10 仍然适用:
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement; […]
强调我的。这实际上意味着在丢弃的语句中对实体的 ODR 使用不算数。例如:
void blub();
constexpr bool use_blub = false;
void f()
{
if constexpr (use_blub)
{
blub();
}
}
如果条件为假,对blub()
的调用将不需要您的程序定义blub()
。使用普通的 if
,程序仍然需要在某处提供 blub()
的定义,即使从未使用过。因此,例如,您可以使用 if constexpr
在调用某些库函数和调用某些回退实现之间切换,具体取决于库是否可用(并被链接到)。除此之外,假设编译器可能不会警告无法访问的代码,如果它由于 if constexpr
而无法访问,就像它可能与正常的 if
一样。然而,我无法使用任何实际的编译器想出一个这样的例子……
我正在尝试完全理解 if constexpr
。
我明白,如果if constexpr(expr)
在模板中使用,并且expr
依赖于模板参数,那么在实例化过程中,只有then
/[=15之一=] 分支会被实例化,其他的会被丢弃。
我有两个问题:
- 如果
expr
不依赖于模板参数,那么if constexpr(expr)
的任何分支都不会被丢弃,这是真的吗?如果是,标准在哪里这样说?我看不出标准在哪里有例外,只有当expr
依赖时才会发生丢弃。 if constexpr
在模板之外有用吗?如果是,这有哪些用例?你能举一些例子来理解它的用处吗?
Is it true, that if
expr
is not dependent on a template parameter, then no branches ofif constexpr(expr)
will be discarded? If yes, where does the standard say so? […]
是的,确实如此。您正在寻找 [stmt.if]/2。具体这部分:
[…] During the instantiation of an enclosing templated entity, if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated. […]
我能找到的最好的例子是 cppreference.com:
template<class T> void g() {
auto lm = [](auto p) {
if constexpr (sizeof(T) == 1 && sizeof p == 1) {
// this condition remains value-dependent after instantiation of g<T>
}
};
}
Is
if constexpr
useful outside of templates? If yes, can you give some examples to understand its usefulness?
虽然当 if constexpr
没有出现在模板内部时所有分支都将被实例化,但 [basic.def.odr]/10 仍然适用:
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement; […]
强调我的。这实际上意味着在丢弃的语句中对实体的 ODR 使用不算数。例如:
void blub();
constexpr bool use_blub = false;
void f()
{
if constexpr (use_blub)
{
blub();
}
}
如果条件为假,对blub()
的调用将不需要您的程序定义blub()
。使用普通的 if
,程序仍然需要在某处提供 blub()
的定义,即使从未使用过。因此,例如,您可以使用 if constexpr
在调用某些库函数和调用某些回退实现之间切换,具体取决于库是否可用(并被链接到)。除此之外,假设编译器可能不会警告无法访问的代码,如果它由于 if constexpr
而无法访问,就像它可能与正常的 if
一样。然而,我无法使用任何实际的编译器想出一个这样的例子……