在模板之外“ if constexpr”有用吗?

时间:2018-12-02 23:28:24

标签: c++ c++17 constexpr if-constexpr template-instantiation

我试图全面了解if constexpr

我了解,如果if constexpr(expr)用于模板,而expr依赖于模板参数,则在实例化期间,仅then / else中的一个分支将被实例化,其他将被丢弃。

我有两个问题:

  • 是真的,如果expr不依赖于模板参数,那么if constexpr(expr)的分支将不会被丢弃吗?如果是,那么标准在哪里说呢?我看不到该标准在哪里有例外,只有在expr依赖时才会发生丢弃。
  • if constexpr在模板之外有用吗?如果是,这有什么用例?您可以举一些例子来了解它的用处吗?

1 个答案:

答案 0 :(得分:5)

  

是真的,如果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仍然适用:

  

每个程序均应准确地包含该程序中使用的每个非内联函数或变量的一个定义,被丢弃的语句之外; […]

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

void blub();

constexpr bool use_blub = false;

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

如果条件为假,则对blub()的调用将不需要您的程序具有blub()的定义。使用普通的if,即使从未使用过该程序,仍然需要该程序在某处提供blub()的定义。因此,例如,您可以使用if constexpr在调用某些库函数和调用某些后备实现之间切换,具体取决于库是否可用(并链接到)。除此之外,假设地,如果编译器由于if constexpr而无法访问代码,则可能不会发出警告,就像普通的if可能会发出警告一样。但是,我无法使用任何实际的编译器来举一个例子。