如何将任意代码块作为参数传递给C宏

How to pass arbitrary code block to C macro as a param

本文关键字:参数传递 任意 代码      更新时间:2023-10-16

我想创建一个宏,它将接受任意代码块作为其参数,如

FOR_VECTOR( type, vect, code_block ) 
  for( vector<type>::iterator i=vect.begin(); i!=vect.end(); ++i ) { 
    code_block; 
  }

问题是参数中的代码块,它可能包含任意数量的,)字符。

有什么好的解决方案吗?

有许多可能的解决方案。

如果您只需要一个表达式(而不是一个完整的代码块),您可以将其包含在()

FOR_VECTOR( int, v, (func(i,1)) )

将工作-(func(i,1))被视为单个宏参数

另一个部分解决方案是可变宏,如果预处理器支持的话。

您可以定义宏

#define COMMA ,
#define LPAR (
#define RPAR )

并使用它们来形成您的代码块,而不是真正的( ,)

FOR_VECTOR( int, v, func LPAR i COMMA 1 RPAR )

不过,它的可读性不是很强。

或者,您可以在宏替换后注释掉字符串文字的引号:

FOR_VECTOR( type, vect, code_block ) 
  for( vector<type>::iterator i=vect.begin(); i!=vect.end(); ++i ) { 
    /code_block/; 
  }
FOR_VECTOR( int, v, *"*/ func(i,1); proc(i,2); /*"* )

如@mas.morozov所述,您可以使用可变宏:

#include <iostream>
#include <vector>
#define FOR_VECTOR( type, vect, ... ) 
  for( std::vector<type>::iterator i=vect.begin(); i!=vect.end(); ++i ) { 
    __VA_ARGS__ 
  }
int main()
{
    std::vector<int> v = {1, 2, 3, 4, 5, 6};
    FOR_VECTOR(int, v, {
        std::cout << *i << std::endl;
    })
}

你可以在这里在线玩:https://godbolt.org/z/oLWV-z

我在这里找到了解决方案:https://mort.coffee/home/obscure-c-features/

您还可以制作一个更通用的FOR_CONTAINER宏:

#include <iostream>
#include <vector>
#define FOR_CONTAINER( container, ... ) 
  for( decltype(container)::iterator i=container.begin(); i!=container.end(); ++i ) { 
    __VA_ARGS__ 
  }
int main()
{
    std::vector<int> v = {1, 2, 3, 4, 5, 6};
    FOR_CONTAINER(v, {
        std::cout << *i << std::endl;
    })
}

请在此处尝试:https://godbolt.org/z/9Gzqja