Компилятор Visual С++ допускает зависимое имя как тип без имени типа?

Сегодня один из моих друзей сказал мне, что следующий код хорошо компилируется в его Visual Studio 2008:

#include <vector>
struct A
{
  static int const const_iterator = 100;
};
int i;
template <typename T>
void PrintAll(const T & obj)
{
  T::const_iterator *i;
}
int main()
{
  std::vector<int> v;
  A a;
  PrintAll(a);
  PrintAll(v);
  return 0;
}

Я обычно использую g++, и он всегда отказывается передать второй вызов PrintAll(). Насколько я знаю, для этой проблемы g++ делает стандартный способ перевода шаблона.

Итак, мои знания неверны или это расширение VS2008?


person hpsMouse    schedule 04.06.2010    source источник
comment
Это с /Za (строгий) или /Ze (по умолчанию, расширения)?   -  person MSalters    schedule 04.06.2010
comment
@MSalters: только что попробовал с /Za. Разницы не увидел...   -  person hpsMouse    schedule 04.06.2010


Ответы (2)


Это вообще не расширение.

VC++ никогда не реализовывал интерпретацию двух фаз должным образом:

  1. В момент определения проанализируйте шаблон и определите все независящие имена
  2. В момент создания убедитесь, что шаблон создает допустимый код.

VC++ никогда не реализовывал первую фазу... это неудобно, поскольку это означает не только то, что он принимает несовместимый код, но и то, что в некоторых ситуациях он создает совершенно другой код.

void foo(int) { std::cout << "int" << std::endl; }

template <class T> void tfoo() { foo(2.0); }

void foo(double) { std::cout << "double" << std::endl; }

int main(int argc, char* argv[])
{
  tfoo<Dummy>();
}

С этим кодом:

  • совместимые компиляторы будут печатать «int», потому что это было единственное определение, доступное в момент определения шаблона, а разрешение foo не зависит от T.
  • VC++ напечатает «двойной», потому что он никогда не беспокоился о фазе 1.

Это может показаться глупым в том, что касается различий, но если вы думаете о количестве включений, которые у вас есть в большой программе, есть риск, что кто-то введет перегрузку после кода вашего шаблона... и БАМ :/

person Matthieu M.    schedule 04.06.2010
comment
Есть ли способ заставить VC++ генерировать хотя бы предупреждение? Такое поведение является неприятностью для кода, который должен работать в нескольких компиляторах. Разработчики в нашей команде время от времени забывают добавить ключевое слово, и код не компилируется на Clang - person Samaursa; 05.02.2015
comment
@Samaursa: К сожалению, я не знаю. Если вы используете Clang, вам может быть интересно узнать, что они разрабатывают подключаемый драйвер для VC++, чтобы вы могли вызывать Clang непосредственно из Visual Studio. - person Matthieu M.; 05.02.2015

Я не уверен, что «расширение» — это именно то, как я бы описал VC++ в этом отношении, но да, gcc в этом отношении лучше соответствует.

person Jerry Coffin    schedule 04.06.2010
comment
Разве это не поведение Visual Studio в разрешительном режиме? Я думаю, что он будет отвергать код в строгом режиме и реализует это расширение для обратной совместимости с VC6. - person MSalters; 04.06.2010