【发布时间】:2014-01-04 18:00:03
【问题描述】:
最近我正在研究著名的“两阶段名称查找”对模板类中名称的确切含义。尽管我已经阅读了很多关于这方面的文章,但我仍然无法了解这方面的一切。现在我对下面显示的代码感到困惑:
template<typename T>
class A
{
public:
void f(T, T){};
};
namespace ns
{
typedef int TT;
void f(int, int){};
};
template<typename T>
class B : public A<T>
{
public:
void g()
{
//f(T(), T()); // it's fine for error here
typedef ns::TT TTT;
f(TTT(), T()); // why this issued an error?
f(ns::TT(), T()); // and this?
}
};
/* I also think it's OK to move ns here */
// namespace ns
// {
// typedef int TT;
// void f(int, int){};
//};
int main()
{
B<int> b;
b.g();
}
请注意第二条评论。由于“f”是一个依赖名称,它的查找应该延迟到“main”函数中的实例化。那时,编译器应该在主函数的范围内执行参数依赖名称查找。我认为现在它应该发现命名空间 ns 中的函数,但它仍然发出编译错误:
1.cpp: In instantiation of 'void B<T>::g() [with T = int]':
1.cpp:30:6: required from here
1.cpp:23:15: error: 'f' was not declared in this scope, and no declarations were found by argument-dependent lookup at the point of instantiation [-fpermissive] f(TTT(), T()); //why this issued an error?
^
1.cpp:23:15: note: declarations in dependent base 'A<int>' are not found by unqualified lookup
1.cpp:23:15: note: use 'this->f' instead
有人可以向我解释一下吗?谢谢。
【问题讨论】:
-
[basic.lookup.argdep]/2 "对于函数调用中的每个参数类型
T,都有一组零个或多个关联的命名空间和一组零个或多个关联的类可以考虑。命名空间和类的集合完全由函数参数的类型(以及任何模板模板参数的命名空间)决定。用于指定类型的 Typedef 名称和 using-declarations 对这个集合没有贡献." [强调我的] 我认为这个问题与模板无关。 -
那么第三条评论出现的错误呢? f(ns::TT(), T())?
-
那么
ns::TT是int的类型定义。而ns不是int的关联命名空间。同样的规则也适用。 (ns::的存在只会更改::之后的TT的名称查找,它不会更改f的名称查找 - 这仍然仅取决于参数的类型。) -
啊 - 等等,我不知何故忽略了继承。在非限定查找期间不搜索基类范围,因为基类
A<T>是依赖的。 -
@DyP,好的,谢谢!那么.. 此外,您能否向我展示一个在类似情况下参数依赖名称查找生效的示例?
标签: c++ templates name-lookup