3

这个模板函数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>()

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

因此,如果我的假设是正确的,那么下面的程序将始终在每个编译器和每个设置中打印 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#2C++17 中的“If constexpr”在非模板函数中不起作用

如果if语句的形式为if constexpr,则条件的值应为 bool 类型的上下文转换的常量表达式;这种形式称为constexpr if语句。如果转换条件的值为假,则第一个子语句是丢弃的语句,否则第二个子语句(如果存在)是丢弃的语句。在封闭模板化实体的实例化过程中,如果条件在其实例化后不依赖于值,则丢弃的子语句(如果有)不会被 实例化。[ 注意:废弃语句中的 Odr 使用不需要定义实体。— 尾注]案例默认值出现在这种if语句中的标签应与同一if语句中的 switch 语句相关联。在 constexpr if 语句的子语句中声明的标签只能由同一子语句中的语句引用。

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

4

1 回答 1

4

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

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

[stmt.if](强调我的)

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

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

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

于 2019-05-28T05:14:29.840 回答