条件运算符的返回类型和两阶段查找 [英] Conditional operator's return type and two-phase lookup

查看:110
本文介绍了条件运算符的返回类型和两阶段查找的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下代码段:

struct Base { };
struct Derived : Base { };

void f(Base &) { std::cout << "f(Base&)\n"; }

template <class T = int>
void g() {
    Derived d;
    f(T{} ? d : d); // 1
}

void f(Derived &) { std::cout << "f(Derived&)\n"; }

int main() {
    g();
}

在这种情况下,我认为应该在第一阶段查找在// 1处对f的函数调用,因为其参数类型明确地为Derived&,因此被解析为f(Base&),即范围只有一个.

In this case, I reckon that the function call to f at // 1 should be looked up in phase one, since its argument's type is unambigously Derived&, and thus be resolved to f(Base&) which is the only one in scope.

Clang 3.8.0同意我的观点,但GCC 6.1.0不会,并且将f的查询推迟到第二阶段,在第二阶段选择f(Derived&).

Clang 3.8.0 agrees with me, but GCC 6.1.0 doesn't, and defers the lookup of f until phase two, where f(Derived&) is picked up.

哪个编译器是正确的?

推荐答案

使用 n4582 .

在第14.6节(p10)中,如果名称不依赖于模板参数,则该名称将在声明时绑定.如果它依赖于模板参数,则在14.6.2节中定义.

In section 14.6 (p10) it says the name is bound at the point of declaration if the name is not dependent on a template parameter. If it depends on a template parameter this is defined in section 14.6.2.

第14.6.2.2节继续说,如果任何子表达式是类型相关的,则表达式是类型相关的.

Section 14.6.2.2 goes on to say an expression is type dependent if any subexpression is type dependent.

现在,因为对f()的调用取决于其参数.您查看参数类型以查看它是否取决于类型.参数为False<T>::value ? d : d.这里的第一个条件取决于类型T.

Now since the call to f() is dependent on its parameter. You look at the parameter type to see if it is depending on the type. The parameter is False<T>::value ? d : d. Here the first conditional is depending on the type T.

因此,我们得出的结论是,调用是在实例化而不是声明时绑定的.因此,应绑定到:void f(Derived &) { std::cout << "f(Derived&)\n"; }

Therefore we conclude that the call is bound at the point of instantiation not declaration. And therefore should bind to: void f(Derived &) { std::cout << "f(Derived&)\n"; }

因此g ++的实现更为准确.

Thus g++ has the more accurate implementation.

14.6名称解析[temp.res]

第10段:

如果名称不依赖于模板参数(如14.6.2中定义),则该名称的声明(或声明集)应在以下范围内:名称出现在模板定义中;该名称绑定到在该点找到的一个或多个声明,并且该绑定不受实例化时可见的声明的影响.

14.6 Name resolution [temp.res]

Para 10:

If a name does not depend on a template-parameter (as defined in 14.6.2), a declaration (or set of declarations) for that name shall be in scope at the point where the name appears in the template definition; the name is bound to the declaration (or declarations) found at that point and this binding is not affected by declarations that are visible at the point of instantiation.

除如下所述外,如果任何子表达式与类型有关,则表达式与类型有关.

Except as described below, an expression is type-dependent if any subexpression is type-dependent.

这篇关于条件运算符的返回类型和两阶段查找的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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