我试图查阅关于do_run解析的标准,并发现“对于使用非限定名称查找(3.4.1)或限定名称查找(3.4.3)查找的部分,仅 找到模板定义上下文中的函数声明“。上下文究竟是什么?
在以下示例中,do_run(int)
以某种方式“隐藏”do_run(domain::mystruct)
,编译器抱怨o can't be converted to int
。如果我发表评论do_run(int)
,则do_run(domain::mystruct)
对run
可见,并且代码已编译。这种行为是否与标准中提到的“背景”有关?在我看来do_run(int)
和do_run(domain::mystruct)
应该对(可解析)运行可见。
namespace domain {
struct mystruct { };
}
void do_run(domain::mystruct) { cout << "do_run(domain::mystruct)" << endl; }
namespace lib { namespace details {
template <class T>
class runner {
public:
void run(T t) { do_run(t); }
};
void do_run(int) { cout << "do_run(int)" << endl; }
}}
int main() {
domain::mystruct o;
lib::details::runner<domain::mystruct> r;
r.run(o);
return 0;
}
在do_run(int)
出现时,我需要额外的步骤将do_run(domain::mystruct)
带入“上下文”。有三种方式:
do_run(domain::mystruct)
放入命名空间域。do_run(domain::mystruct)
放入名称空间lib :: details。using ::do_run
醇>
所以我推断出上下文是名称空间lib :: details和namespace domain?
编译器VS2010
答案 0 :(得分:1)
查找取决于它是否是依赖名称。由于函数调用取决于模板参数类型T
(通过使用此类型的对象t
调用),因此它是一个从属名称。
仅在定义模板的上下文中查找非依赖名称。不考虑与实际实例化有关的任何内容:由于名称被确定为不依赖于模板参数,因此将实例化考虑在内是没有意义的。这是第一阶段的查找。
在考虑实例化的情况下查找依赖函数名称。这将使用所有参数并确定关联的命名空间,以仅在这些关联的命名空间中查找函数。对于内置类型,添加的关联命名空间是全局命名空间。对于其他类型,添加的关联命名空间是它们所在的命名空间以及所有封闭的命名空间。此外,还添加了从类定义中可见的事物的关联命名空间:基类的关联命名空间,模板,模板参数的命名空间等。这是阶段II查找,也称为参数依赖的外观-up (我认为这些术语并不完全相同,当然,细节并不像上面描述的那么简单)。
在您引用的代码中,显然,do_run()
中的lib::details::runner<domain::mystruct>
函数位于全局命名空间中。如果将其移至domain
,也会发现它。命名空间do_run()
中的lib::details
方法在实例化lib::details::runner<int>
中找不到 ,但是int
的关联命名空间只是全局命名空间但是函数不在那里,直到实例化才查找它,因为它是一个从属名称。
那就是说,我的理解是MSVC ++没有按照指定的方式实现两阶段名称查找,但我不知道它偏离的方式。