Dynamic_cast в assert Причинить ошибку
Я использую устаревшую Visual Studio 2008 (позвольте мне избавить вас от проблемы "там ваша проблема".) Это, похоже, проблема с Visual Studio: http://rextester.com/XKFR77690 Кажется, что проблема связана с макросом assert
: http://ideone.com/bhxMi0
Учитывая эти структуры:
struct base { virtual ~base() {} };
template <typename T>
struct Foo : base { T foo; };
Я могу это сделать:
base* test = new Foo<pair<int, int>>;
if(dynamic_cast<Foo<pair<int, int>>*>(test) != NULL) cout << "hello world\n";
Но когда я использую тот же самый код, что и в if
-statement в assert
: assert(dynamic_cast<Foo<pair<int, int>>*>(test) != NULL)
, я получаю сообщение об ошибке:
предупреждение C4002: слишком много фактических параметров для макроса assert
ошибка C2143: синтаксическая ошибка: отсутствует ',' before ')'
Кстати, я могу исправить это, используя C-стиль: assert((Foo<pair<int, int>>*)(test) != NULL)
Но я думаю, что C-Style будет делать static_cast
не a dynamic_cast
, который я не хочу.
Ответы
Ответ 1
assert
- макрос. Он обрабатывается препроцессором, который ничего не знает о конструкциях на С++. Итак, следующее:
assert(dynamic_cast<Foo<pair<int, int>>*>(test) != NULL)
расширяется до функционально подобранного макроса с двумя аргументами, которые в этом случае:
dynamic_cast<Foo<pair<int
и
int>>*>(test) != NULL
Помните, что аргументы макросов, подобные функции, разделяются запятыми. Это все препроцессор видит. Таким образом, в этом случае он видит 2 аргумента вместо 1 аргумента, требуемого assert
.
Ваша версия исполнения в стиле C работает случайно из-за скобок, которые имеют более высокий приоритет, чем запятая. Помещая их вокруг dynamic_cast
, тоже выполняет эту работу.
Ответ 2
Yup: макросы обрабатывают запятые верхнего уровня как разделители аргументов. Самое простое исправление - поместить круглые скобки вокруг нарушающего кода:
assert((dynamic_cast<Foo<pair<int, int>>*>(test)) != NULL)
или, если хотите, круглые скобки вокруг всего содержимого:
assert((dynamic_cast<Foo<pair<int, int>>*>(test) != NULL))
Причина, по которой C-стиль заключается в компиляции вопроса, заключается не в том, что это приведение в стиле C, но в том, что он помещает код шаблона в круглые скобки, поэтому запятая больше не находится на самом удаленном уровне.