【问题标题】:c++: the context of an unqualified name lookup in a templatec++:模板中非限定名称查找的上下文
【发布时间】:2012-11-21 20:29:31
【问题描述】:

我尝试查阅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. 在命名空间 lib::details 中添加 using ::do_run

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

编译器VS2010

【问题讨论】:

    标签: c++ templates namespaces argument-dependent-lookup


    【解决方案1】:

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

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

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

    在你引用的代码中,do_run() 在全局范围内的函数显然是在lib::details::runner&lt;domain::mystruct&gt; 中找到的,因为它在全局命名空间中。如果它被移动到domain,它也会被找到。命名空间lib::details 中的do_run() 方法not 在实例化lib::details::runner&lt;int&gt; 中找到,但是:int 的关联命名空间只是全局命名空间,但该函数不存在并且它直到实例化才被查找,因为它是一个从属名称。

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

    【讨论】:

    • 好的,如果定义了 lib::details::do_run(int),则找不到 do_run(domain::mystruct)。我想我应该在另一个编译器上试试这个。
    • 是的,这是一个编译器问题。发布的代码(带有明显添加的标头和 using 指令)确实使用 gcc 编译。
    • 谢谢,我确认它是在 GCC4.7 中编译的。
    猜你喜欢
    • 1970-01-01
    • 2013-07-17
    • 1970-01-01
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-18
    相关资源
    最近更新 更多