此模板函数f<X>()
总是不实例化吗?
if constexpr(something false){
//some template function OR function in template class
f<X>();
}
下面是我的测试(coliru MCVE)。
我创建了fun<S>()
,它将在且仅当E<S>
时实例化S!=void
。
然后我叫fun<void>()
,fun<int>()
和fun<float>()
。
我相信if constexpr(false)
会强制C ++编译器跳过#1
的{{1}}部分。
我的fun<void>()
应该只有countRunner
2次。
因此,如果我的假设是正确的,下面的程序将始终在每个编译器和每个设置中打印2。
(它为我打印了2张,但仅凭实验无法证明。)
++
我可以依靠#include<iostream>
int countRunner=0;
template<class T> class E{
public: static int countIndex;
public: E(){
if(false){
int unused=E::countIndex;
}
}
};
template<class T> int E<T>::countIndex=countRunner++;
template<class S> void fun(){
if constexpr(!std::is_same_v<void,S>){
E<S> e; //#1 - S=int,float, but never void
}
}
int main (){
fun<void>();
fun<int>();
std::cout<<"testResult="<<countRunner<<std::endl;
fun<float>();
}
永远不会被实例化吗?
请提供一些(半)官方参考,以使我冷静下来。
编辑:我刚刚找到了http://eel.is/c++draft/stmt.if#2和"If constexpr" in C++17 does not work in a non-templated function。
如果 if 语句的格式为 if constexpr ,则 条件应为的上下文转换常量表达式 布尔型;这种形式称为 constexpr if 语句。如果值 的转换条件为假,则第一个子语句为 丢弃的语句,否则第二个子语句(如果存在)是 废弃的声明。在实例化封闭期间 模板实体,如果条件在其后不依赖于值 实例化,被丢弃的子语句(如果有)不是 实例化 。 [注意:不需要的语句中的Odr-uses不需要 要定义的实体。 —注释] 案例或默认标签 出现在这样的 if 语句中的语句应与 在同一 if 语句中的switch语句。在标签中声明的标签 如果声明只能由constexpr声明, 同一子语句中的一条语句。
我仍然不确定规则中的“实例化”一词。它与“模板实例化”中的含义相同吗?
答案 0 :(得分:4)
它与“模板实例化”中的含义相同吗?
是的,确实如此。该规范称“废弃”语句,仅在某些实例化模板实体的模板实例化上下文中具有含义。
[stmt.if] (强调我的意思)
2如果if语句为if constexpr形式,则 条件应为的上下文转换常量表达式 布尔型;这种形式称为constexpr if语句。如果值 的转换条件为假,则第一个子语句为 丢弃的语句,否则第二个子语句(如果存在)是 废弃的声明。 在封装实例期间 模板实体,如果条件在其后不依赖于值 实例化,被丢弃的子语句(如果有)不是 实例化。
重要的是,替换参数后条件取决于值。一方面,这意味着如果条件仅取决于要实例化的立即封闭模板的参数,则它不会成为该模板实例化的一部分。
在您的情况下,这完全意味着如果std::is_same_v<void,S>
为true,则“ if”的主体将不属于实例化的fun<void>
的一部分。