7

N4527 14.6 [温度分辨率]/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 定义上下文和实例化点之间的差异

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

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

4

1 回答 1

7

这是一个例子:

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 和 GCC 实际上会f用这段代码调用不同的 s。

于 2015-12-09T04:38:22.070 回答