是否“如果constexpr(something false)”总是忽略模板实例化

时间:2019-05-28 04:21:15

标签: c++ language-lawyer c++17 if-constexpr template-instantiation

此模板函数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声明,   同一子语句中的一条语句。

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

1 个答案:

答案 0 :(得分:4)

  

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

是的,确实如此。该规范称“废弃”语句,仅在某些实例化模板实体的模板实例化上下文中具有含义。

  

[stmt.if] (强调我的意思)

     

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

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

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