C++ assert: the precedence of the expression in an assert macro

断了今生、忘了曾经 提交于 2020-01-10 03:33:08

问题


In C++:

  assert(  std::is_same<int , int>::value  ); // does not compile

  assert( (std::is_same<int , int>::value) ); // compiles

Can anyone explain why?


回答1:


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 ,



回答2:


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.



来源:https://stackoverflow.com/questions/24793706/c-assert-the-precedence-of-the-expression-in-an-assert-macro

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!