Вопрос

рассмотрим следующую программу:

    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. Даже после прочтения раздела о Koenig Lookup в стандарте ISI я не уверен, что это поведение соответствует стандарту. Это? Кто-нибудь знает способ обойти это поведение, не квалифицируя вызов размера с префиксом NS3?

Заранее спасибо!

Это было полезно?

Решение

Аргументы шаблона и базовые классы влияют на ADL, поэтому я думаю, что GCC верен, здесь: NS3 происходит из текущей области, NS1 из аргумента шаблона X и NS2 из базового класса аргумента шаблона.

Вы должны как-то устранить неоднозначность; Я бы предложил переименовать одну или несколько функций, если это возможно, или, возможно, использовать SFINAE для устранения неоднозначности функций.

(Аналогичная ситуация: обратите внимание, что boost :: noncopyable на самом деле " typedef noncopyable _ :: noncopyable noncopyable; " так, что пространство имен boost не добавляется в набор типов ADL, производных от него.)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top