Макрос С++ "##" не работает после оператора "->"
У меня есть объект shared_ptr x, который имеет методы get и set следующим образом:
x->a_value();
x->set_a_value();
x->b_value();
x->set_b_value();
Когда я пытаюсь определить макрос:
#define MAC(type) \
x->set_##type##_value(val);
MAC(a)
Он отлично работает, но когда я это делаю:
#define MAC(type) \
x->##type##_value();
MAC(a)
он дает следующую ошибку компиляции: pasting formed '->a', an invalid preprocessing token
Ответы
Ответ 1
Препроцессор работает на "токенах" - любит имена и операторы.
Оператор ##
создает новый токен, вставляя меньшие части вместе. В первом примере set_##type##_value
становится set_a_value
, который является допустимым токеном.
Во втором примере ->##type##_value
станет ->a_value
, что не является допустимым токеном препроцессора. Это должно быть два токена.
Если вы просто сделаете строку x->type##_value();
он должен работать. Вы получаете отдельные токены x
, ->
, a_value
, (
, )
и ;
,
Ответ 2
Что он говорит на олове: ->a
- не один, действительный токен препроцессора: это два токена. Вам не нужно вставлять сюда.
#define MAC(type) \
x->type##_value();
Ответ 3
Оператор токена (##
) используется для объединения двух токенов в один действительный токен.
Когда вы пишете
x->##type##_value();
-
Первый обработанный токен равен x
.
-
Следующий токен формируется путем объединения типа токена ->
с type
, поскольку type
является a
, результатом конкатенации является ->a
, который должен быть действительным токеном, но не является.
Следовательно, вы получаете ошибку: pasting formed '->a', an invalid preprocessing token
.
Чтобы исправить это, просто напишите
x->type##_value();
Сюда
-
Первый обработанный токен равен x
.
-
Следующий обработанный токен ->
.
-
Следующий токен формируется путем объединения type
токена (который становится a
) с маркером _value
. Это дает значение a_value
, которое является действительным токеном.
-
Следующий токен (
.
-
Следующий токен )
.
-
Последний токен ;
,