"if constexpr"在模板之外有用吗?

gez*_*eza 7 c++ constexpr c++17 if-constexpr template-instantiation

我想if constexpr完全理解.

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

我有两个问题:

  • 是真的,如果expr不依赖于模板参数,那么if constexpr(expr)将不会丢弃任何分支?如果是,标准在哪里这样说?我没有看到标准有什么例外,丢弃只在expr依赖时发生.
  • if constexpr模板以外有用吗?如果是,这有什么用例?你能举出一些例子来了解它的用处吗?

Mic*_*zel 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>
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

if constexpr模板以外有用吗?如果是,您能举一些例子来了解它的用处吗?

虽然所有分支都if constexpr不会在模板内部出现时进行实例化,但[basic.def.odr]/10仍然适用:

每个程序应该只包含每个非内联函数或变量的一个定义,该函数或变量在废弃语句之外的程序中使用.[...]

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

void blub();

constexpr bool use_blub = false;

void f()
{
    if constexpr (use_blub)
    {
        blub();
    }
}
Run Code Online (Sandbox Code Playgroud)

调用blub()不会要求您的程序定义blub()条件是否为假.使用普通if程序,程序仍然需要提供blub()某个地方的定义,即使它从未使用过.因此,您可以使用if constexpr在调用某些库函数和调用某些回退实现之间切换,具体取决于库是否可用(以及链接到).除此之外,假设编译器可能不会警告无法访问的代码,如果由于if constexpr它可能与正常情况相似而无法访问if.我无法用任何实际的编译器提出这个例子,但是......