Вставка токенов означает «объединение двух токенов в один токен».
Вам этого не нужно.ptr_to_item->a()
это не один токен.Предполагая, что ptr_to_item
является именем переменной, оно равно 5: ptr_to_item
, ->
, a
, (
, )
.
Ваш макрос должен быть просто:
#define DO_STUFF(item, getter, setter, k) do { \
int value = (item)->getter(); \
//... \
(item)->setter(newValue); \
} while(0);
Кстати, для ненавистников макросов это позволяет избежать макросов, а также избежать использования функции указателя на член в качестве параметра функции.Это можно попробовать, если макрос работает быстрее, чем функция спрашивающего, поскольку вызов через указатель не является встроенным.Я не знаю, если / когда это будет иметь значение:
#include <iostream>
struct A {
int f;
int foo() {return f;}
void setfoo(int a) { f = a; }
};
template <typename T, typename U, U (T::*GETTER)(), void (T::*SETTER)(U)>
void doit(T &obj, U k) {
U value = (obj.*GETTER)();
value += k;
(obj.*SETTER)(value);
}
int main() {
A a = {0};
std::cout << a.foo() << "\n";
doit<A,int,&A::foo, &A::setfoo>(a,1);
std::cout << a.foo() << "\n";
doit<A,int,&A::foo, &A::setfoo>(a,2);
std::cout << a.foo() << "\n";
}
Потому что это есть.
Есть по крайней мере одна слабость.Вы не можете быть ссылочным типом в шаблоне.Но поскольку в коде, о котором идет речь, он фактически зафиксирован как int
, параметр шаблона U может вообще не понадобиться, так что, надеюсь, это не слишком ограничивает.