Koenig Lookup的奇怪行为

时间:2009-09-14 14:51:07

标签: c++ templates g++ argument-dependent-lookup

考虑以下计划:

    namespace NS2 {
      class base { };

      template<typename T>
      int size(T& t) {
        std::cout << "size NS2 called!" << std::endl;
        return sizeof(t);
      } 
    };

    namespace NS1 {
      class X : NS2::base { };
    }

    namespace NS3 {
      template<typename T>
      int size(T& t) {
        std::cout << "size NS3 called!" << std::endl;
        return sizeof(t) + 1;
      }

      template<typename T>
      class tmpl 
      {
      public:
        void operator()() { size(*this); }
      };
    };

int main() +{
  NS3::tmpl<NS1::X> t;
  t();
  return 0;
}

我的编译器(gcc 4.3.3)不编译程序,因为对size的调用是不明确的。名称空间NS2似乎被添加到类tmpl中的size调用的关联名称空间集合中。即使在阅读了ISI标准中有关Koenig Lookup的部分后,我也不确定这种行为是否符合标准。是吗? 有没有人知道解决此问题的方法而不用NS3前缀限定大小调用?

提前致谢!

1 个答案:

答案 0 :(得分:8)

模板参数和基类都会影响ADL,所以我认为GCC是正确的,这里:NS3来自当前作用域,NS1来自X模板参数,NS2来自模板参数的基类。

你必须以某种方式消除歧义;如果可行的话,我建议重命名一个或多个函数,或者使用SFINAE来消除函数的歧义。

(类似情况:请注意,boost :: noncopyable实际上是“typedef noncopyable _ :: noncopyable noncopyable;”,因此boost命名空间不会被添加到从它派生的ADL类型集中。)