Que*_*tin 39 c++ dependent-name language-lawyer compiler-bug name-lookup
请考虑以下代码段:
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();
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我认为应该在第一阶段查找对fat 的函数调用// 1,因为它的参数的类型是明确的Derived&,因此可以解析为f(Base&)范围中唯一的一个.
Clang 3.8.0同意我的观点,但是GCC 6.1.0没有,并推迟f到第二阶段的查找,在那里f(Derived&)被选中.
哪个编译器是对的?
Mar*_*ork 23
在第14.6节(p10)中,如果名称不依赖于模板参数,则表示名称在声明点处绑定.如果它取决于模板参数,则在第14.6.2节中定义.
第14.6.2.2节接着说,如果任何子表达式是类型相关的,则表达式是类型相关的.
现在,因为调用f()依赖于它的参数.您查看参数类型以查看它是否取决于类型.参数是False<T>::value ? d : d.这里第一个条件取决于类型T.
因此,我们得出结论,调用是在实例化而不是声明的情况下绑定的.因此应该绑定到:void f(Derived &) { std::cout << "f(Derived&)\n"; }
因此g ++具有更准确的实现.
14.6名称解析[temp.res]
第10段:
如果名称不依赖于模板参数(如14.6.2中所定义),则该名称的声明(或声明集)应在名称出现在模板定义中的范围内; 该名称绑定到此时发现的声明(或声明),并且此绑定不受在实例化时可见的声明的影响.
14.6.2.2依赖于类型的表达式[temp.dep.expr]
除非如下所述,否则如果任何子表达式依赖于类型,则表达式依赖于类型.
| 归档时间: |
|
| 查看次数: |
1085 次 |
| 最近记录: |