Nic*_*hen 8 c++ gcc templates clang argument-dependent-lookup
我有一个NB::B<T>
从NA::A
命名空间中的非模板类派生的模板类.act<T>
是模板函数add_ref
在其模板参数的实例上调用函数.具体来说,act<NB::B<int>>
想要使用ADL 找到add_ref
在NB::B
base 的名称空间中定义的内容.完整的例子如下:
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>();
}
Run Code Online (Sandbox Code Playgroud)
这个编译好了gcc
(4.7.0).在Comeau
网上.但是clang
(3.1)失败了:
a.cpp:4:3: error: use of undeclared identifier 'add_ref'
Run Code Online (Sandbox Code Playgroud)
同时,标准如下:
3.4.2/2 ......
- 如果T是template-id,则其关联的名称空间和类是定义模板的名称空间; 对于成员模板,成员模板的类; 与模板类型参数(模板模板参数除外)提供的模板参数类型相关联的名称空间和类; 定义任何模板模板参数的名称空间; 以及定义用作模板模板参数的任何成员模板的类.
令人惊讶的是,模板的基础未列为关联命名空间的路径.因此clang
,这种行为似乎是正确的.而Comeau
与gcc
正在接受不正确的程序.
同时,3.4.2/3
规定using
的在参数的命名空间没有任何效果:
在考虑关联的命名空间时,查找与关联命名空间用作限定符时执行的查找相同(3.4.3.2),但以下情况除外:
- 忽略关联命名空间中的任何using-directive.
但是,当我取消对using NA::add_ref
线clang
很高兴编译测试.
为了把我的例子转化为实际的角度来看,你可以认为这act
是一个方法boost::intrusive_ptr
,add_ref(A*)
是intrusive_ptr_add_ref(CBase*)
和B
是一些模板,从基地获得CBase
.
关于这一点,我有几个问题:
我是正确的clang
的是正确的拒绝我的测试程序,gcc
以及Comeau
不按标准?
是否有理由为什么标准指定了这种不切实际的行为(不允许将模板类库作为关联的命名空间)?
是否clang
接受我的测试程序与using NA::add_ref
指令的理由是错误的3.4.2/3
?
我应该报告错误吗?:)
PS我已经阅读过clang语言兼容性常见问题解答,但在那里找不到答案.
从n3337开始,基本上是C++ 11并进行了少量的编辑修改,3.4.2/2读取:
对于函数调用中的每个参数类型T [...]命名空间和类的集合按以下方式确定:[...]
- 如果T是类类型(包括联合),则其关联的类是:类本身; 它所属的成员,如果有的话; 而其直接和间接基类.其关联的名称空间是其关联类是成员的名称空间.此外,如果T是一个类模板专业化,...
然后继续使用您在问题中发布的相同报价.这里最重要的区别是还的,这意味着您引用(我省略)名单是除了已经提到的命名空间,以及包括命名空间,其基类是其成员.
Gcc和comeau是正确的,而clang ++在拒绝代码时是错误的.
<不适用>
Clang ++在没有它的情况下拒绝它是错误的using NA::add_ref
.
是的,您应该报告错误.似乎已经报道并修复了它.
归档时间: |
|
查看次数: |
706 次 |
最近记录: |