16,3 / 9:
в последовательности предварительной обработки
токены, составляющие вызов
функциональный макрос, новая строка
считается нормальным пробелом
характер.
Так что многострочный вызов макроса в целом нормален. Конечно, если DOSOMETHING
и DOANOTHERTHING
не вводят фигурные скобки для области, то ваш конкретный пример переопределит k
.
Edit:
Мы не можем использовать функторы, потому что нам нужно
иметь доступ к контексту
вызов. Мы не можем использовать лямбду (сниф), потому что мы используем старый компилятор
Обычный способ - захватывать любые переменные, которые вам нужны в функторе, как лямбда. Единственное, что лямбда может сделать, что функтор не может, - это «захватить все» без необходимости печатать ее, но тот, кто пишет лямбду, может видеть, какие переменные они используют, так что это просто удобство, они могут напечатать их все, если должен был. В вашем примере:
struct MyFunctor {
int o;
MyFunctor(int o) : o(o) {}
void operator()() const { // probably not void in practice
int k = AFunction();
k++;
AnotherFunction( k + o );
}
};
template<typename F>
void DoThings(const F &f) {
DOSOMETHING(f());
DOANOTHERTHING(f());
}
int my_function() {
int o = RandomNumber();
DoBothThings(MyFunctor(o));
}
Вы также можете захватывать переменные по ссылке (обычно используя указатель в качестве элемента данных, а не ссылку, так что функтор может быть назначен для копирования).
Если под «контекстом» вы подразумеваете, например, что аргумент макроса и / или тело макроса могут содержать break
или goto
и, следовательно, должны находиться внутри лексической области действия вызывающей стороны, тогда вы можете ' не использовать функтор или лямбду. К стыду; -)