Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 通过模板类的基进行参数相关的查找_C++_Templates_Gcc_Clang_Argument Dependent Lookup - Fatal编程技术网

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_refline
clang
取消注释
时,我很乐意编译测试

从实际角度来看,您可以认为,
act
boost::intrusive\u ptr
的一种方法,
add\u ref(a*)
intrusive\u ptr\u add\u ref(CBase*)
,而
B
是一些模板,源自base
CBase

关于这一点,我有几个问题:

  • 我认为
    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
  • 的情况下拒绝它是错误的

  • 是的,您可能应该报告一个bug。看来已经上报并修复了


  • C++11模式有用吗?C++11似乎已经澄清了措辞,因为实际上
    NB::B
    是一个类(碰巧是一个模板专门化),而不是一个模板。(规则IIUC是,与类型为专门化的模板关联的名称空间被添加到与类关联的名称空间中。)这不是很脆弱吗?在某些时候,您可能会添加一个默认的
    add_ref
    实现,它总是比直接基的相关名称空间更匹配?@LucDanton,您是对的。这两点(关于
    class
    template id
    的相关名称空间)都适用于class
    template 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'