“if constexpr(something false)”是否始终忽略模板实例化

cpp*_*ner 4 c++ language-lawyer c++17 if-constexpr template-instantiation

这个模板函数f<X>()总是不会被实例化吗?

\n\n
if constexpr(something false){\n     //some template function OR function in template class\n     f<X>();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

以下是我的测试(coliru MCVE)。
\n我创建了当且仅当 时fun<S>()才会实例化。\n然后我调用,和。E<S>S!=void
fun<void>()fun<int>()fun<float>()

\n\n

我相信if constexpr(false)强制 C++ 编译器#1跳过fun<void>().
\n我的countRunner应该++只有2次。

\n\n

因此,如果我的假设成立,下面的程序将始终在每个编译器和每个设置中打印 2。

\n\n

(它为我打印了 2,但仅凭实验并不能证明什么。)

\n\n
#include<iostream>\nint countRunner=0;\ntemplate<class T> class E{\n    public: static int countIndex;\n    public: E(){\n        if(false){\n            int unused=E::countIndex;\n        }\n    }\n};\ntemplate<class T> int E<T>::countIndex=countRunner++;\ntemplate<class S> void fun(){\n    if constexpr(!std::is_same_v<void,S>){\n        E<S> e;  //#1  - S=int,float, but never void\n    }\n}\nint main (){\n    fun<void>();\n    fun<int>();\n    std::cout<<"testResult="<<countRunner<<std::endl;\n    fun<float>();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我可以相信它E<void>永远不会被实例化吗?
\n请提供一些(半)官方参考资料,让我冷静下来。

\n\n

编辑:我刚刚发现http://eel.is/c++draft/stmt.if#2“If constexpr” in C++17 does not work in a non-templated function

\n\n
\n

如果if语句的形式为if constexpr,则条件的值应为根据上下文转换的 bool 类型常量表达式;这种形式称为constexpr if语句。如果转换条件的值为 false,则第一个子语句是废弃语句,否则第二个子语句(如果存在)是废弃语句。在外围模板化实体的实例化过程中,如果条件在其实例化后不依赖于值,则不会实例化被丢弃的子语句(如果有 。[\xe2\x80\x89注意:废弃语句中的 Odr-uses 不需要定义实体。\xe2\x80\x94\xe2\x80\x89end note \xe2\x80\x89]此类if语句中出现的casedefault标签应与同一if语句中的 switch 语句相关联。constexpr if 语句的子语句中声明的标签只能由同一子语句中的语句引用。

\n
\n\n

我仍然不确定规则中的“实例化”一词。它与“模板实例化”中的含义相同吗?

\n

Sto*_*ica 5

它与“模板实例化”中的含义相同吗?

是的,它确实。该规范谈到“丢弃”语句,并且仅在某些封闭模板化实体的模板实例化上下文中才有意义。

[stmt.if](强调我的)

2如果 if 语句的形式为 if constexpr,则条件的值应为根据上下文转换的 bool 类型常量表达式;这种形式称为 constexpr if 语句。如果转换后的条件的值为 false,则第一个子语句是被丢弃的语句,否则第二个子语句(如果存在)是被丢弃的语句。在封闭模板化实体的实例化期间,如果条件在其实例化后不依赖于值,则不会实例化被丢弃的子语句(如果有)

重要的一点是参数替换后条件与值相关。一方面,这意味着如果条件仅取决于正在实例化的直接封闭模板的参数,则它不会成为该模板实例化的一部分。

在您的情况下,这意味着如果std::is_same_v<void,S>为 true,则“if”的主体将不会成为实例化的一部分fun<void>

  • @cppBeginner - 我从未遇到过它在其他上下文中使用。 (2认同)