c – 在模板中执行参数依赖名称查找时的奇怪行为
最近,我正在研究模板类中名称的众所周知的“两阶段名称查找”的确切含义.虽然我已经阅读了很多关于此的文章,但我仍然无法了解这一切.现在我对下面显示的代码感到困惑:
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”函数中的实例化.此时,编译器应在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 有人可以向我解释一下吗?谢谢. 解决方法
依赖于参数的查找仅搜索参数类型的关联类和名称空间. typedef只是一个透明的别名,类似于using声明.
从标准n3485草案,[basic.lookup.argdep] / 2关于依赖于参数的查找:
[强调我的] template<typename T> class A { public: void f(T,int){}; }; template<typename T> class B : public A<T> // note the base class is dependent { public: void g() { //f(T(),T()); // and this? } }; 由于基类是相关的,因此在非限定查找期间不会搜索它.因此,可以使用参数依赖查找找到f.您正确地声明f将仅在“第二阶段”(在实例化时)搜索,如在您的调用中,至少一个参数依赖于模板参数. 但是,ns不是依赖名称,也不是TT(在ns :: TT中).因此,名称空间和TT必须在它们用于g的定义之前声明. 无论是编写f(ns :: TT(),T())还是f(T(),T())都不会影响在参数依赖查找期间搜索f的一般规则:只有关联的命名空间和类参数的类型(T和ns :: TT).两者都是B< int> :: g()的整数,因此没有关联的类和名称空间. f(TTT(),TTT())改变查找,因为现在f是在名字查找阶段查找(它不是从属名称). 以下是依赖于参数的查找示例: namespace ns { struct TT {}; void f(TT,TT) {} } int main() { ns::TT x; f(x,x); } 现在,您也可以在类模板的成员函数中执行此操作: namespace ns { struct TT {}; void f(TT,TT) {} } template<typename T> struct B { void g() { f(T(),T()); } }; int main() { B<ns::TT> x; x.g(); } 但是,正如我所说,依赖于参数的名称查找不适用于诸如int之类的基本类型. 在上面的示例中,f再次依赖,因为至少一个参数依赖于模板参数.因此,您也可以写: template<typename T> struct B { void g() { f(T(),T()); // looked up during the second phase,// from the point of instantiation } }; namespace ns { struct TT {}; void f(TT,TT) {} } int main() { B<ns::TT> x; x.g(); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |