cpp*_*ner 4 c++ language-lawyer c++17 if-constexpr template-instantiation
这个模板函数f<X>()总是不会被实例化吗?
if constexpr(something false){\n //some template function OR function in template class\n f<X>();\n}\nRun Code Online (Sandbox Code Playgroud)\n\n以下是我的测试(coliru MCVE)。
\n我创建了当且仅当 时fun<S>()才会实例化。\n然后我调用,和。E<S>S!=voidfun<void>()fun<int>()fun<float>()
我相信if constexpr(false)强制 C++ 编译器#1跳过fun<void>().
\n我的countRunner应该++只有2次。
因此,如果我的假设成立,下面的程序将始终在每个编译器和每个设置中打印 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}\nRun Code Online (Sandbox Code Playgroud)\n\n我可以相信它E<void>永远不会被实例化吗?
\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\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语句中出现的case或default标签应与同一if语句中的 switch 语句相关联。constexpr if 语句的子语句中声明的标签只能由同一子语句中的语句引用。
\n
我仍然不确定规则中的“实例化”一词。它与“模板实例化”中的含义相同吗?
\n它与“模板实例化”中的含义相同吗?
是的,它确实。该规范谈到“丢弃”语句,并且仅在某些封闭模板化实体的模板实例化上下文中才有意义。
[stmt.if](强调我的)
2如果 if 语句的形式为 if constexpr,则条件的值应为根据上下文转换的 bool 类型常量表达式;这种形式称为 constexpr if 语句。如果转换后的条件的值为 false,则第一个子语句是被丢弃的语句,否则第二个子语句(如果存在)是被丢弃的语句。在封闭模板化实体的实例化期间,如果条件在其实例化后不依赖于值,则不会实例化被丢弃的子语句(如果有)。
重要的一点是参数替换后条件与值相关。一方面,这意味着如果条件仅取决于正在实例化的直接封闭模板的参数,则它不会成为该模板实例化的一部分。
在您的情况下,这意味着如果std::is_same_v<void,S>为 true,则“if”的主体将不会成为实例化的一部分fun<void>。