首页 文章

c中定义上下文和实例化点之间非依赖构造的解释差异

提问于
浏览
4

N4527 14.6 [temp.res] / p8如果由于不依赖于模板参数的构造而在其定义之后立即对模板进行假设实例化,则该程序是不正确的;无需诊断 . 如果在假设实例中对这种结构的解释与模板的任何实际实例中对应结构的解释不同,则该程序是不正确的;无需诊断 . [注意:在包括以下情况的情况下可能会发生这种情况:(8.1) - 非依赖名称中使用的类型在定义模板但在执行实例化时完成时不完整,或者(8.2) - 实例化使用默认参数或默认模板参数,该参数尚未在定义模板时定义,或者(8.3) - 模板实例化中使用的常量表达式评估(5.20)(8.3.1) - 整数或无范围枚举类型的const对象的值或(8.3.2) - constexpr对象的值或(8.3.3) - 引用的值或(8.3.4) - constexpr的定义函数,并且在定义模板时未定义该实体,或

那么,这些代码是否格式错误?

代码1:

extern double b;

template<class T>
void f(T=b){}

void g(){
    f<double>();//ill-formed or not?
}

double b = 0;

void h(){
    f<double>();//ill-formed or not?
}

代码2:

//translation 1
extern double b;

template<class T>
void f(T=b){}

void g(){
    f<double>();//ill-formed or not?
}

//translation 2
double b = 0;

Issue1850 Differences between definition context and point of instantiation

模板中非依赖引用所引用的实体的各种特征可以在定义上下文和该模板的特化的实例化点之间改变 . 这些包括初始化(影响对象是否可以在常量表达式中使用),函数和模板默认参数以及类型的完整性 . 关于在定义上下文中还是在实例化时检查这些是否存在实现差异 . 如果这种参考的有效性在两种情况之间发生变化,则可能需要一条规则来使其形成不良,不需要诊断 .

你能告诉我更多关于两个上下文之间非依赖名称特征如何不同的例子吗?通常约为8.2和8.3.1

1 回答

  • 4

    这是一个例子:

    extern const int b;
    
    template<int, int>
    void f(int);
    
    template<int, const int &>
    void f(long);
    
    template<class>
    void g() {
        f<0, b>(0);
    }
    // #1
    
    extern const int b = 0;
    
    
    int main(){
        g<int>(); 
    }
    
    // #2
    

    在#1处的假设实例化将调用 void f<0, b>(long) ,因为 b 在该点不是常量表达式,因此 (int) 过载SFINAE . #2(这是 g<int> 的实例化点)的实例化将调用 void f<0, 0>(int) ,因为那时 b 是一个常量表达式, (int) 重载是可行的并且赢得重载解析 .

    Clang and GCC will in fact call different fs with this code.

相关问题