C ++断言:断言宏中表达式的优先级

时间:2014-07-17 01:59:35

标签: c++ c-preprocessor assert operator-precedence

在C ++中:

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

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

任何人都可以解释原因吗?

2 个答案:

答案 0 :(得分:14)

assert是预处理器宏。预处理器宏是愚蠢的;他们不懂模板。预处理器在括号内看到10个令牌:

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

它以逗号分隔。它不知道这是错误的分割位置,因为它不理解std::is_same<intint>::value不是有效的C ++表达式。

预处理器 足够聪明,不会在多个参数中分解内部括号对的内容。这就是为什么添加额外的括号可以解决问题。

答案 1 :(得分:11)

逗号被视为宏的参数分隔符,但第二种情况下的括号会保护参数。我们可以通过转到草案C ++标准部分16.3 宏替换来看到这一点(强调我的):

  

由最外部限制的预处理令牌序列   匹配括号形成类似函数的参数列表   宏。列表中的各个参数用逗号分隔   预处理标记,但逗号在匹配之间预处理标记   内括号不分开参数。如果有序列   在参数列表中预处理标记,否则   充当预处理指令,154行为未定义

我们可以看到宏扩展在语义分析之前发生,转到2.2 部分翻译并看到阶段4包括:

  

执行预处理指令,扩展宏调用,   [...]然后删除所有预处理指令。

和第7阶段包括:

  

[...]每个预处理令牌都转换为令牌。 (2.7)。该   产生的标记在语法和语义上进行分析   翻译为翻译单位[...]

作为旁注,我们可以看到Boost包含一个特殊的宏来处理这种情况: BOOST_PP_COMMA

  

BOOST_PP_COMMA宏扩展为逗号。

并说:

  

预处理器将逗号解释为宏调用中的参数分隔符。因此,逗号需要特殊处理。

和一个例子:

BOOST_PP_IF(1, BOOST_PP_COMMA, BOOST_PP_EMPTY)() // expands to ,