In C++:
assert( std::is_same<int , int>::value ); // does not compile
assert( (std::is_same<int , int>::value) ); // compiles
Can anyone explain why?
In C++:
assert( std::is_same<int , int>::value ); // does not compile
assert( (std::is_same<int , int>::value) ); // compiles
Can anyone explain why?
The comma is being treated as a argument separator for the macro, but parenthesis in your second case protect the arguments. We can see this by going to the draft C++ standard section 16.3
Macro replacement which says (emphasis mine):
The sequence of preprocessing tokens bounded by the outside-most matching parentheses forms the list of arguments for the function-like macro. The individual arguments within the list are separated by comma preprocessing tokens, but comma preprocessing tokens between matching inner parentheses do not separate arguments. If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives,154 the behavior is undefined
We can see that macro expansion happens before semantic analysis by going to section 2.2
Phases of translation and see that phase 4 is includes:
Preprocessing directives are executed, macro invocations are expanded, and [...] All preprocessing directives are then deleted.
and phase 7 includes:
[...]Each preprocessing token is converted into a token. (2.7). The resulting tokens are syntactically and semantically analyzed and translated as a translation unit[...]
As a side note we can see the Boost includes a special macro to deal with this situation: BOOST_PP_COMMA:
The BOOST_PP_COMMA macro expands to a comma.
and says:
The preprocessor interprets commas as argument separators in macro invocations. Because of this, commas require special handling.
and an example:
BOOST_PP_IF(1, BOOST_PP_COMMA, BOOST_PP_EMPTY)() // expands to ,
assert
is a preprocessor macro. Preprocessor macros are dumb; they don't understand templates. The preprocessor sees 10 tokens within the parentheses:
assert( std :: is_same < int , int > :: value );
It splits at the comma. It doesn't know that this is the wrong place to split at, because it doesn't understand that std::is_same<int
and int>::value
aren't valid C++ expressions.
The preprocessor is smart enough to not break up the contents of inner pairs of parentheses across multiple arguments. That's why adding the extra parentheses fixes the problem.