11

I'm using the antiquated Visual Studio 2008 (let me save you the trouble "there's your problem".) This seems to be a problem with Visual Studio: http://rextester.com/XKFR77690 This seems to be a problem with the assert macro: http://ideone.com/bhxMi0

Given these structs:

struct base { virtual ~base() {} };

template <typename T>
struct Foo : base { T foo; };

I can do this:

base* test = new Foo<pair<int, int>>;

if(dynamic_cast<Foo<pair<int, int>>*>(test) != NULL) cout << "hello world\n";

But when I use the exact same code as is in the if-statement in an assert: assert(dynamic_cast<Foo<pair<int, int>>*>(test) != NULL) I get an error:

warning C4002: too many actual parameters for macro assert
error C2143: syntax error : missing ',' before ')'

Incidentally I can fix this by using a C-style cast: assert((Foo<pair<int, int>>*)(test) != NULL) But I think that the C-Style cast will do a static_cast not a dynamic_cast which I don't want.

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288

2 Answers2

10

Yup: macros treat top-level commas as argument separators. The simplest fix is to put parentheses around the offending code:

assert((dynamic_cast<Foo<pair<int, int>>*>(test)) != NULL)

or, if you prefer, parentheses around the entire content:

assert((dynamic_cast<Foo<pair<int, int>>*>(test) != NULL))

The reason the C-style cast in the question compiles is not that it's a C-style cast, but that it puts the template code in parentheses, so the comma is no longer at the outermost level.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
9

assert is a macro. It's handled by the preprocessor which knows nothing about C++ constructs. So the following:

assert(dynamic_cast<Foo<pair<int, int>>*>(test) != NULL)

expands to a function-like macro taking two arguments, which in this case are:

dynamic_cast<Foo<pair<int

and

int>>*>(test) != NULL

Remember that function-like macro arguments are separated by commas. That is all the preprocessor sees. So in this case it sees 2 arguments instead of the 1 argument required by assert.

Your C-style cast version works incidentally because of the parentheses, which have higher precedence than the comma. Putting them around the dynamic_cast does the job as well.

DeiDei
  • 10,205
  • 6
  • 55
  • 80
  • Re: "answer below me" -- SO rearranges answers depending on various factors, so "below" and "above" can change. Right now, for instance, I don't see any answer below yours, but I do see one above it. – Pete Becker Nov 02 '16 at 15:58
  • @PeteBecker I spent 20 seconds searching for the right word and *below* was my last resort... – DeiDei Nov 02 '16 at 15:59
  • @DeiDei Just link the answer. – Jonathan Mee Nov 02 '16 at 15:59