C ++中定义上下文和实例化点之间非依赖性构造的解释差异 [英] Differences of the interpretation of a non-dependent construct between definition context and point of instantiation in c++

查看:122
本文介绍了C ++中定义上下文和实例化点之间非依赖性构造的解释差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

N4527 14.6 [温度]/p8

N4527 14.6 [temp.res]/p8

如果立即假设模板实例化 由于其定义不依赖模板参数,因此遵循其定义的格式将不正确, 该程序格式不正确;无需诊断.如果在 假设的实例化在任何实际中都与相应构造的解释不同 模板的实例化,程序格式不正确;无需诊断. [注意:这可能会发生 在以下情况下:

If a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, the program is ill-formed; no diagnostic is required. If the interpretation of such a construct in the hypothetical instantiation is different from the interpretation of the corresponding construct in any actual instantiation of the template, the program is ill-formed; no diagnostic is required. [ Note: This can happen in situations including the following:

(8.1)-非依赖名称中使用的类型在定义模板时是不完整的,但是 在执行实例化时完成,或者

(8.1) — a type used in a non-dependent name is incomplete at the point at which a template is defined but is complete at the point at which an instantiation is performed, or

(8.2)-实例化使用未在处定义的默认参数或默认模板参数 模板定义的点

(8.2) — an instantiation uses a default argument or default template argument that had not been defined at the point at which the template was defined, or

(8.3)-模板实例化使用中的常量表达式求值(5.20)

(8.3) — constant expression evaluation (5.20) within the template instantiation uses

(8.3.1)— 整数或无范围枚举类型的const对象的值

(8.3.2)-constexpr对象或

(8.3.2) — the value of a constexpr object or

(8.3.3)-引用或

(8.3.3) — the value of a reference or

(8.3.4)— constexpr函数的定义,

(8.3.4) — the definition of a constexpr function,

并且在定义模板时未定义该实体,或者

and that entity was not defined when the template was defined, or

那么,这些代码格式不正确吗?

So, are these codes ill-formed?

代码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;

问题1850定义上下文和实例化点之间的差异

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

Various characteristics of entities referred to by a non-dependent reference in a template can change between the definition context and the point of instantiation of a specialization of that template. These include initialization (which affects whether an object can be used in a constant expression), function and template default arguments, and the completeness of types. There is implementation divergence as to whether these are checked in the definition context or at the point of instantiation. Presumably a rule is needed to make it ill-formed, no diagnostic required, if the validity of such a reference changes between the two contexts.

您能否向我展示更多有关两个上下文之间非依赖名称的特征有何不同的示例?通常约为8.2和8.3.1

Can you show me more examples about how are characteristics of non-dependent names different between the two contexts? Typically about 8.2 and 8.3.1

推荐答案

下面是一个示例:

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)重载是可行的,并且赢得了重载解决方案.

A hypothetical instantiation at #1 will call void f<0, b>(long), because b isn't a constant expression at that point, so the (int) overload SFINAEs away. An instantiation at #2 (which is a point of instantiation of g<int>) will call void f<0, 0>(int), because by then b is a constant expression, the (int) overload is viable and wins overload resolution.

Clang和GCC实际上会使用此代码调用不同的f.

这篇关于C ++中定义上下文和实例化点之间非依赖性构造的解释差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆