为什么结构必须与模板类位于同一命名空间中才能编译

Why does a struct have to be in the same namespace as a template class in order to compile?

本文关键字:命名空间 于同一 编译 结构 为什么      更新时间:2023-10-16

问题的标题并没有透露太多关于我的问题,但我试图用一个短语来解释这个问题。这就是问题所在,我在Windows中的MinGW和Linux中的GCC编译的应用程序中具有类似的代码结构。Visual Studio没有任何问题。结构如下:

#include <iostream>
namespace idb
{
    class Wrapper
    {
    public:
        template<typename S>
        void boo(S& s)
        {
            bind(s);
        }
    };
}
namespace idb // <- if this namespace changes, code explodes
{
    struct Fulalas
    {
        int x;
    };
}
namespace idb
{
    void bind(idb::Fulalas f)
    {
        std::cout << f.x << std::endl;
    }
}
namespace app
{
    class Foo
    {
    public:
        void func()
        {
            idb::Fulalas f;
            f.x = 5;
            w.boo(f);
        }
    private:
        idb::Wrapper w;
    };
}
int main()
{
    app::Foo f;
    f.func();
    return 0;
}

问题是为什么在GCC/MinGW中将idb::Fulalas更改为aaa::Fulalas(或任何所需的名称)会产生以下错误:

..namespacemain.cpp: In instantiation of 'void idb::Wrapper::boo(S&) [with S = aaa::Fulalas]':
..namespacemain.cpp:41:11:   required from here
..namespacemain.cpp:11:10: error: 'bind' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive]
    bind(s);
          ^
..namespacemain.cpp:26:7: note: 'void idb::bind(aaa::Fulalas)' declared here, later in the translation unit
  void bind(aaa::Fulalas f)

这与结构无关。

这是关于bind和参数依赖查找。

  • 什么是"参数相关查找"(又名 ADL 或"Koenig 查找")?
  • http://en.cppreference.com/w/cpp/language/adl

bind 是非限定的,因此在关联的命名空间中查找它。如果struct与该绑定重载不在同一命名空间中,则不会看到/考虑它。

在表达式中

bind(s)

名称bind是相关的,因为参数s的类型为 S,即模板参数。依赖名称在模板实例化点绑定。当您调用时会发生这种情况

w.boo(f);

从而使用类型 S = idb::Fulalas 实例化boo。解析依赖名称时,将考虑来自两个源的声明:

  • 模板定义点可见的声明。
  • 来自
  • 与函数参数类型关联的命名空间的声明,这些命名空间都来自 实例化上下文 (14.6.4.1) 和定义上下文。

([临时部门])

因此,如果名称是在模板的定义点之后但在实例化点之前声明的,则只能通过 ADL 找到它,而不能通过普通的非限定名称查找找到它。普通的非限定查找只能查找在模板定义点可见的名称,而不是在实例化点可见的名称。因此,如果Fulalas未在与bind相同的命名空间中声明,则 ADL 将找不到idb::bind的声明,并且名称查找将完全失败。

相关文章: