3

我尝试查阅有关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)进入“上下文”。有三种方式:

  1. 放入do_run(domain::mystruct)命名空间域。
  2. 放入do_run(domain::mystruct)命名空间 lib::details。
  3. using ::do_run在命名空间 lib::details 中添加。

所以我推断上下文是命名空间 lib::details 和命名空间域?

编译器VS2010

4

1 回答 1

1

查找取决于它是否是从属名称。由于您的函数调用取决于模板参数类型T(通过使用t此类型的对象调用),因此它是一个依赖名称。

仅在定义模板的上下文中查找非依赖名称。与实际实例化相关的任何内容都不会被考虑在内:由于名称被确定为不依赖于模板参数,因此将实例化考虑在内是没有意义的。这是第一阶段的查找。

在考虑实例化的情况下查找从属函数名称。这使用所有参数并确定关联的名称空间以仅在这些关联的名称空间中查找函数。对于内置类型,添加的关联命名空间是全局命名空间。对于其他类型,添加的关联命名空间是它们所在的命名空间加上所有封闭的命名空间。此外,添加了从类定义中可见的事物的关联名称空间:基类的关联名称空间,对于模板,模板参数的名称空间等。这是第二阶段查找,也称为参数相关查找(我认为这些术语并不完全相同,当然细节也没有上面描述的那么简单)。

在您引用的代码do_run()中,显然lib::details::runner<domain::mystruct>可以在全局名称空间中找到全局范围内的函数。如果将其移至domain. 但是,在实例化中找不到命名空间中的do_run()方法:关联的命名空间只是全局命名空间,但该函数不存在,并且在实例化之前不会查找它,因为它是一个依赖名称。lib::detailslib::details::runner<int>int

也就是说,我的理解是 MSVC++ 没有按照指定的方式实现两阶段名称查找,但我不知道它偏离了哪些方式。

于 2012-11-21T20:52:55.453 回答