"if constexpr(something false)" 是否总是忽略模板实例化
Does "if constexpr(something false)" ALWAYS omit template instantiation
此模板函数 f<X>()
是否始终不实例化?
if constexpr(something false){
//some template function OR function in template class
f<X>();
}
下面是我的测试(coliru MCVE)。
我创建了 fun<S>()
当且仅当 S!=void
.
时才会实例化 E<S>
然后我调用 fun<void>()
、fun<int>()
和 fun<float>()
.
我相信 if constexpr(false)
强制 C++ 编译器跳过 fun<void>()
的 #1
部分。
我的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>();
}
我可以相信 E<void>
永远不会被实例化吗?
请提供一些(半)官方参考资料让我冷静下来。
编辑: 我刚找到 http://eel.is/c++draft/stmt.if#2 and "If constexpr" in C++17 does not work in a non-templated function。
If the if statement is of the form if constexpr, the value of the
condition shall be a contextually converted constant expression of
type bool; this form is called a constexpr if statement. If the value
of the converted condition is false, the first substatement is a
discarded statement, otherwise the second substatement, if present, is
a discarded statement. During the instantiation of an enclosing
templated entity, if the condition is not value-dependent after its
instantiation, the discarded substatement (if any) is not
instantiated. [ Note: Odr-uses in a discarded statement do not require
an entity to be defined. — end note ] A case or default label
appearing within such an if statement shall be associated with a
switch statement within the same if statement. A label declared in a
substatement of a constexpr if statement shall only be referred to by
a statement in the same substatement.
规则中的 "instantiated" 这个词我还是不太确定。它与"template instantiation"中的含义相同吗?
Does it have the same meaning as in "template instantiation"?
是的,确实如此。该规范谈到 "discarded" 语句,并且仅在某些封闭模板化实体的模板实例化上下文中有意义。
[stmt.if] (emphasis mine)
2 If the if statement is of the form if constexpr, the value of
the condition shall be a contextually converted constant expression of
type bool; this form is called a constexpr if statement. If the value
of the converted condition is false, the first substatement is a
discarded statement, otherwise the second substatement, if present, is
a discarded statement. During the instantation of an enclosing
templated entity, if the condition is not value-dependent after its
instantiation, the discarded substatement (if any) is not
instantiated.
重要的一点是参数被替换后的条件是value-dependent。一方面,这意味着如果条件仅取决于正在实例化的直接封闭模板的参数,则它不会成为该模板实例化的一部分。
在你的例子中,这意味着如果 std::is_same_v<void,S>
为真,"if" 的主体将不会成为实例化 fun<void>
的一部分。
此模板函数 f<X>()
是否始终不实例化?
if constexpr(something false){
//some template function OR function in template class
f<X>();
}
下面是我的测试(coliru MCVE)。
我创建了 fun<S>()
当且仅当 S!=void
.
时才会实例化 E<S>
然后我调用 fun<void>()
、fun<int>()
和 fun<float>()
.
我相信 if constexpr(false)
强制 C++ 编译器跳过 fun<void>()
的 #1
部分。
我的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>();
}
我可以相信 E<void>
永远不会被实例化吗?
请提供一些(半)官方参考资料让我冷静下来。
编辑: 我刚找到 http://eel.is/c++draft/stmt.if#2 and "If constexpr" in C++17 does not work in a non-templated function。
If the if statement is of the form if constexpr, the value of the condition shall be a contextually converted constant expression of type bool; this form is called a constexpr if statement. If the value of the converted condition is false, the first substatement is a discarded statement, otherwise the second substatement, if present, is a discarded statement. During the instantiation of an enclosing templated entity, if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated. [ Note: Odr-uses in a discarded statement do not require an entity to be defined. — end note ] A case or default label appearing within such an if statement shall be associated with a switch statement within the same if statement. A label declared in a substatement of a constexpr if statement shall only be referred to by a statement in the same substatement.
规则中的 "instantiated" 这个词我还是不太确定。它与"template instantiation"中的含义相同吗?
Does it have the same meaning as in "template instantiation"?
是的,确实如此。该规范谈到 "discarded" 语句,并且仅在某些封闭模板化实体的模板实例化上下文中有意义。
[stmt.if] (emphasis mine)
2 If the if statement is of the form if constexpr, the value of the condition shall be a contextually converted constant expression of type bool; this form is called a constexpr if statement. If the value of the converted condition is false, the first substatement is a discarded statement, otherwise the second substatement, if present, is a discarded statement. During the instantation of an enclosing templated entity, if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.
重要的一点是参数被替换后的条件是value-dependent。一方面,这意味着如果条件仅取决于正在实例化的直接封闭模板的参数,则它不会成为该模板实例化的一部分。
在你的例子中,这意味着如果 std::is_same_v<void,S>
为真,"if" 的主体将不会成为实例化 fun<void>
的一部分。