为什么结构必须与模板类位于同一命名空间中才能编译
Why does a struct have to be in the same namespace as a template class in order to compile?
问题的标题并没有透露太多关于我的问题,但我试图用一个短语来解释这个问题。这就是问题所在,我在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
的声明,并且名称查找将完全失败。
相关文章:
- Qt C++:不同文件中同一命名空间的多个Q_NAMESPACE
- 为什么 std::variant 找不到运算符<() 当与比较类不在同一命名空间中时
- 初始化命名空间中的变量是否类似于将它们初始化为类成员?
- 在同一函数中使用不同的命名空间
- 运算符<<依赖于参数的查找不在全局命名空间中查找
- 试图将两个类放在同一命名空间中的单独文件中,但只有#1个#Class类作品
- 在同一命名空间中声明变量和函数是否出错?[C++]
- 如何使函数模板仅适用于特定命名空间中的类型
- 在全局命名空间中重载不依赖于用户定义类型的标准定义类型的运算符是否格式正确?
- 我是否可以在类似于 C# 的 C++ 中创建全局命名空间层次结构,以帮助开发人员使用我们的代码?
- 为什么在语句"std::cout << std::endl;"中使用时需要命名空间限定,给定依赖于参数的查找?
- 依赖于参数的查找在来自另一个命名空间的别名类型上意外行为
- 依赖于参数的名称查找:添加要查找的额外命名空间
- 非本地C++11 lambdas是否存在于匿名命名空间中
- 如何让代码存在于两个或多个非嵌套命名空间的范围内
- 不同文件中同一命名空间中的 2 个不同枚举中的相同标识符
- 为什么结构必须与模板类位于同一命名空间中才能编译
- 来自单独.cpp文件中同一命名空间的 free 函数,C++ 中无法识别
- 用于在 C++ 中管理特定于平台的代码的内联命名空间技术
- 访问 C++ 中同一命名空间中的成员