C++ 通过模板类的基进行参数相关的查找
我有一个模板类C++ 通过模板类的基进行参数相关的查找,c++,templates,gcc,clang,argument-dependent-lookup,C++,Templates,Gcc,Clang,Argument Dependent Lookup,我有一个模板类NB::B派生自命名空间中的非模板类NA::aact是一个模板函数,在其模板参数的实例上调用add_ref函数。具体来说,act希望使用ADL查找add_ref在NB::B的基的命名空间中定义的add_ref。完整示例如下所示: template<class T> void act() { T* p = 0; add_ref(p); // the failing line } namespace NA { struct A { }; // I wan
NB::B
派生自命名空间中的非模板类NA::a
act
是一个模板函数,在其模板参数的实例上调用add_ref
函数。具体来说,act
希望使用ADL查找add_ref
在NB::B
的基的命名空间中定义的add_ref
。完整示例如下所示:
template<class T>
void act() {
T* p = 0;
add_ref(p); // the failing line
}
namespace NA
{
struct A { };
// I want ADL to find this:
void add_ref(A* p) {
}
}
namespace NB
{
// template class with non-template base
template <class T>
struct B: NA::A { };
typedef B<int> Bi;
// using NA::add_ref; // fixes the problem
}
int main()
{
act<NB::Bi>();
}
同时,该标准规定:
3.4.2/2
-如果T是模板id,则其关联的命名空间和类是定义模板的命名空间;对于成员模板,成员模板的类;与为模板类型参数(不包括模板参数)提供的模板参数类型相关联的命名空间和类;定义了任何模板参数的名称空间;以及定义用作模板参数的任何成员模板的类
令人惊讶的是,模板的基并没有列为关联名称空间的路径。因此,clang
的行为似乎是正确的。和Comeau
和gcc
正在接受不正确的程序
同时,3.4.2/3
声明在参数的名称空间中使用
无效:
考虑关联命名空间时,查找与关联命名空间用作限定符(3.4.3.2)时执行的查找相同,但以下情况除外:
-将忽略关联命名空间中的任何using指令
但是当我使用NA::add_reflineclang
取消注释时,我很乐意编译测试
从实际角度来看,您可以认为,act
是boost::intrusive\u ptr
的一种方法,add\u ref(a*)
是intrusive\u ptr\u add\u ref(CBase*)
,而B
是一些模板,源自baseCBase
关于这一点,我有几个问题:
我认为clang
拒绝我的测试程序是正确的,并且gcc
和Comeau
不符合标准,对吗
标准规定了这种不切实际的行为(不允许模板类基作为关联的名称空间)有什么原因吗
以3.4.2/3
为理由,使用NA::add_ref
指令接受带有的测试程序是否有误
我应该报告错误吗?:)
注:我已经读过了,但没有找到答案。来自n3337,它基本上是C++11,只做了一些编辑性的改动,3.4.2/2的内容如下:
对于函数调用[…]中的每个参数类型T
名称空间和类按以下方式确定:[……]
- 如果T是类类型(包括联合),则其关联的类是:类本身;其所属类别(如有);及其直接和间接基类。其关联的名称空间是其关联的类所属的名称空间此外,如果T是类模板专门化
然后,它将继续使用与你在问题中发布的基本相同的引用。这里的重要区别是此外,这意味着您引用的列表(我省略了)是对前面提到的名称空间的补充,其中包括基类是其成员的名称空间
Gcc和comeau是正确的,而clang++拒绝代码是错误的
<不适用>
Clang++在没有使用NA::add_ref
的情况下拒绝它是错误的
C++11模式有用吗?C++11似乎已经澄清了措辞,因为实际上
NB::B
是一个类(碰巧是一个模板专门化),而不是一个模板。(规则IIUC是,与类型为专门化的模板关联的名称空间被添加到与类关联的名称空间中。)这不是很脆弱吗?在某些时候,您可能会添加一个默认的add_ref
实现,它总是比直接基的相关名称空间更匹配?@LucDanton,您是对的。这两点(关于class
和template id
的相关名称空间)都适用于classtemplate id
。@pmr,这确实有点脆弱。虽然我不明白你的评论。如果没有ADL,将找不到任何东西,因为没有任何add\u ref
函数在来自intrusive\u ptr.hpp
@nichtversteen的调用范围内。如果使用默认实现,我的意思是:除非act
函数的范围内有一个函数add\u ref
。命名空间act()
中的模板可以更好地匹配,并且将选择该模板,而不是与基函数关联的函数。该错误在一段时间前已报告并已修复。zhr bug是thag clang没有对模板进行初始化以找到它的基类(以及它的好友声明),谢谢@david rodriguez dribeas。这“进一步”澄清了这个问题。@johannes schaub litb,你还记得你所说的bug的链接吗?我刚刚在一个新构建的clang
trunk上检查了这个问题,但是bug仍然存在。
a.cpp:4:3: error: use of undeclared identifier 'add_ref'