РЕДАКТИРОВАТЬ: Хотя это для C, я думаю, что принятый ответ на Можно ли определить функционально-подобный макрос с переменным телом? может быть здесь использован.
Можно создать макрос таким образом, используя for
l oop. Пример:
#include <iostream>
struct Foo {
int bar;
Foo(int bar) : bar(bar) { std::cout << 1 << std::endl; }
~Foo() { std::cout << 3 << std::endl; }
};
#define TEST(var) \
for (bool flag = true; flag; ) \
for (Foo foo(var); flag; flag = false)
int main()
{
int x = 2;
TEST(x) {
std::cout << foo.bar << std::endl;
}
// std::cout << foo.bar << std::endl; // ERROR: ‘foo’ was not declared in this scope
std::cout << 4 << std::endl;
return 0;
}
Оба цикла будут выполняться, если flag
истинно. Сначала l oop инициализирует flag
этим значением. Второй l oop создает объект foo
. После расширения "тело" TEST
становится телом второго l oop. После выполнения кода (все, что объявлено внутри body, к настоящему времени должно быть должным образом уничтожено), второй l oop устанавливает flag
в false и, следовательно, завершается. Первые петли также заканчиваются и уничтожают flag
.
Проблема в том, что вы хотите использовать его в многопоточной программе. Такой подход обязательно приведет к гонке данных.
Лично я бы не стал экспериментировать с такими макросами, а просто сделал бы что-то таким образом:
using mutex_lock_guard = std::lock_guard<std::mutex>;
std::mutex;
void func(int x)
{
// init...
{
mutex_lock_guard lock(mutex);
// body..
}
}
Или еще с макросами :
#define LOCK_GUARD(var) std::lock_guard<std::mutex> lock(var)
std::mutex;
void func(int x)
{
// init...
{
LOCK_GUARD(mutex);
// body..
}
}