3

考虑以下程序:

    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 中大小调用的关联命名空间集中。即使在阅读了 ISI 标准中关于 Koenig Lookup 的部分之后,我也不确定这种行为是否符合标准。是吗?有没有人知道在不使用 NS3 前缀限定大小调用的情况下解决此行为的方法?

提前致谢!

4

1 回答 1

8

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

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

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

于 2009-09-14T15:12:29.650 回答