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 の size 呼び出しの関連する名前空間のセットに追加されたようです。ISI 標準の Koenig Lookup に関するセクションを読んだ後でも、この動作が標準に準拠しているかどうかはわかりません。それは...ですか?サイズ呼び出しを NS3 プレフィックスで修飾せずに、この動作を回避する方法を知っている人はいますか?

前もって感謝します!

4

1 に答える 1

8

テンプレート引数と基本クラスはどちらも ADL に影響するため、GCC は正しいと思います。ここでは、NS3 は現在のスコープから、NS1 は X テンプレート引数から、NS2 はテンプレート引数の基本クラスから取得されます。

どうにかしてあいまいさを解消する必要があります。可能であれば、1 つ以上の関数の名前を変更するか、SFINAE を使用して関数を明確にすることをお勧めします。

(同様の状況: boost::noncopyable は実際には「typedef noncopyable_::noncopyable noncopyable;」であるため、boost 名前空間は、それから派生した型の ADL セットに追加されないことに注意してください。)

于 2009-09-14T15:12:29.650 に答える