Вы можете использовать троичный оператор, чтобы результат макроса был равен r-значению, но сообщение об ошибке может сбивать пользователей с толку:
struct node {
node *left, *right;
};
#define LEFT( x ) ( true ? (x).left : (node*)0 )
int main() {
node n;
// LEFT( n ); // error
node *l = LEFT( n ); // OK
}
Обман в семантике этого конкретногооператор.Тип выражения, содержащего только оператор, является общим типом (или типом, конвертируемым из) двух ветвей выражения, даже если когда-либо вычисляется только одна из них.Теперь, когда компилятор вычисляет true ? x.left : (node*)0
, он преобразуется в выражение x.left
, но с общим типом x.left
и (node*)0
.Оба они в основном одного и того же типа, с единственной деталью, которая (node*)0
является значением, а не значением l.