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();
}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
