Разрешение области действия для создания экземпляра шаблона

У меня есть следующий набор классов (минимальная репликация моей реальной ситуации):

namespace Parent
{
  class A {};

  namespace Nested
  {
    class A {};
  }

  template <typename T>
  class B
  {
    A myA;
  };
}

Я ожидаю, что элемент Parent::B::myA должен быть однозначно разрешен как относящийся к типу Parent::A. Однако в другом месте моего проекта у меня есть это:

namespace Parent
{
  using namespace Nested;

  void foo()
  {
    B<int> myB;
  }
}

который не компилируется под MSVC 2003:

error C2872: 'A' : ambiguous symbol
        could be 'Test.cpp(5) : Parent::A'
        or       'Test.cpp(9) : Parent::Nested::A'
        Test.cpp(26) : see reference to class template instantiation 'Parent::B<T>' being compiled
        with [ T=int ]

Код будет скомпилирован, если я укажу явно в своем объявлении B::myA, то есть Parent::A myA;. Однако код компилируется в соответствии с gcc-4.3.4. Является ли это просто ошибкой MSVC 2003, или мне действительно нужно беспокоиться о том, в какой области могут создаваться экземпляры моих шаблонов?


person atkins    schedule 22.11.2011    source источник
comment
Это интересно. по-видимому, использование пространства имен работает лексически при создании экземпляра шаблона. это удивительно   -  person sehe    schedule 22.11.2011
comment
FWIW: g++ 4.5.3 соглашается, что это не должно было быть проблемой   -  person sehe    schedule 22.11.2011
comment
@sehe: это не проблема (по стандарту), но MSVC не соответствует стандарту в отношении шаблонов ... (даже в последней версии)   -  person Matthieu M.    schedule 22.11.2011


Ответы (1)


Это давняя ошибка во всех версиях MSVC.

Проблема связана с некорректной реализацией поиска имени в шаблонах в MSVC.

По сути, MSVC будет ждать до момента создания экземпляра, чтобы выполнить поиск имени, в то время как в стандарте явно указано, что правильное поведение заключается в следующем:

  • выполнять поиск имени немедленно (в момент объявления) для независимых символов
  • выполнять поиск имени при создании экземпляра для зависимых символов

Такое поведение позволяет MSVC небрежно относиться к использованию typename или template, потому что он может полностью вывести природу символов (отличить обычные переменные от функций или типов), однако это кошмар, когда кто-то стремится к совместимости с другими компиляторами.

Если можете, откажитесь от MSVC. Если не можешь... удачи.

person Matthieu M.    schedule 22.11.2011
comment
Это восхитительно. Хорошее объяснение - person sehe; 22.11.2011
comment
@sehe: Честно говоря, мне очень грустно, что такой большой продукт не будет стремиться к большему соответствию. Я предполагаю, что это происходит из-за доминирующего положения VC++ на рынке Windows: они не хотят работать лучше, потому что у них нет согласия и, следовательно, нет стимула. - person Matthieu M.; 22.11.2011
comment
нет совпадения -› нет конкуренции? О, и я согласен. См. также блог группы VC++ по C++11 - person sehe; 22.11.2011
comment
@MatthieuM. Спасибо - приятно знать, что происходит, но грустно осознавать, что даже переход на более новый MSVC не поможет! (К сожалению, я не вижу перспективы отказа моей организации от среды MSVC.) Не могли бы вы предложить ссылку, на которую я мог бы ссылаться для будущих читателей моего кода? В противном случае я буду использовать постоянную ссылку на ваш ответ здесь ;-) - person atkins; 22.11.2011
comment
@sehe: спасибо за ссылку, я не следил за последними ходами, и это действительно освещает. Очень плохо, когда у них есть Херб Саттер на такой высокой должности как в MS, так и в комитете C++, что C++ в конечном итоге станет гражданином второй зоны :( - person Matthieu M.; 22.11.2011