繁体   English   中英

考虑模板参数的参数依赖外观(ADL)?

[英]Argument Dependent Look (ADL) considering template arguments?

我有几个命名空间,每个命名空间都有一个名为f的函数模板。

// f() and Widget
namespace A {
  struct Widget { };

  template <typename T>
  void func(const T&) { }
}

// f() and caller()
namespace B {
  template <typename T>
  void func(const T&) { }

  template <typename T>
  void caller(const T& t) {
    func(t); // error occurs here
  }
}

template <typename T>
class Wrap { };

int main() {
  Wrap<A::Widget> w{};
  B::caller(w); // triggers error
}

上面产生以下错误

error: call of overloaded ‘func(const Wrap<A::Widget>&)’ is ambiguous
     func(t);
     ~~~~^~~
note: candidate: void B::func(const T&) [with T = Wrap<A::Widget>]
   void func(const T&) { }
        ^~~~
note: candidate: void A::func(const T&) [with T = Wrap<A::Widget>]
   void func(const T&) { }
        ^~~~

如果Wrap在全局名称空间中,为什么要考虑A::func B::caller不应该呼叫B::func吗?

在模板的情况下,ADL不仅考虑了函数的参数。 在这里,您将Wrap<A::Widget>作为B::caller的参数。 因为callernamespace B ,所以显然考虑了B::func 考虑A::func的原因来自以下(添加了重点)

N659 6.4.2 /(2.2)[basic.lookup.argdep]

如果T是一个类类型(包括并集),则其关联的类为:类本身; 它所属的类(如果有); 及其直接和间接基类。 其关联的名称空间是其关联类的最内部封闭的名称空间。 此外,如果T是类模板专业化,则其关联的名称空间和类还包括:与为模板类型参数提供的模板参数类型相关的名称空间和类 [...]

因为A::WidgetWrap的模板参数,所以A也是Wrap<A::Widget>的关联命名空间

通过使用限定名称来防止ADL,可以使此示例按预期进行编译:

template <typename T>    
void caller(const T& t) {    
  B::func(t);      
}

或将函数名称括在parethese中

template <typename T>    
void caller(const T& t) {    
  (func)(t);      
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM