首页 > 解决方案 > “if constexpr”在模板之外有用吗?

问题描述

我试图if constexpr完全理解。

我理解,如果if constexpr(expr)在模板中使用,并且expr依赖于模板参数,那么在实例化过程中,只有一个then/else分支将被实例化,另一个将被丢弃。

我有两个问题:

标签: c++c++17constexprif-constexprtemplate-instantiation

解决方案


是否真的,如果expr不依赖于模板参数,那么不会if constexpr(expr)丢弃任何分支?如果是,标准在哪里这样说?[…]

是的,这是真的。您正在寻找[stmt.if]/2。具体这部分:

[…] 在封闭模板化实体的实例化期间,如果条件在其实例化后不依赖于值,则不会实例化丢弃的子语句(如果有)。[…]

对于实例化后最终依赖于值的情况,我能找到的最佳示例是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>
        }
    };
}

if constexpr在模板之外有用吗?如果是,你能举一些例子来理解它的用处吗?

if constexpr没有出现在模板中时,所有分支都将被实例化,但[basic.def.odr]/10仍然适用:

每个程序都应包含在该程序中被丢弃的语句之外的每个非内联函数或变量的确切定义;[…]

强调我的。这实际上意味着在废弃语句中对实体的 odr 使用不计算在内。例如:

void blub();

constexpr bool use_blub = false;

void f()
{
    if constexpr (use_blub)
    {
        blub();
    }
}

调用blub()不需要您的程序定义blub()条件是否为假。使用 normal if,程序仍然需要提供blub()某处的定义,即使它从未被使用过。因此,例如,您可以if constexpr根据库是否可用(并链接到)在调用某些库函数和调用某些回退实现之间切换。除此之外,假设编译器可能不会警告无法访问的代码,因为if constexpr它可能由于与正常的if. 我无法使用任何实际的编译器想出一个这样的例子,但是......


推荐阅读