I want to create a macro that will accept arbitrary code block as its parameter like
FOR_VECTOR( type, vect, code_block ) \
for( vector<type>::iterator i=vect.begin(); i!=vect.end(); ++i ) { \
code_block; \
}
The problem is the code block in parameter, which may contain arbitrary number of ,
and )
characters.
Is there any good solution?
There are a number of possible solutions.
If you need only one expression (not a full-fashioned code block) - you can just enclose it in (
and )
FOR_VECTOR( int, v, (func(i,1)) )
will work - (func(i,1))
is treated like single macro argument
Another partial solution is variadic macros, if your preprocessor supports them.
You can define macros
#define COMMA ,
#define LPAR (
#define RPAR )
and use them to form your code block insted of real (
,
and )
FOR_VECTOR( int, v, func LPAR i COMMA 1 RPAR )
It is not very readable though.
Or you can do a trick with commenting out quotes of a string literal after macro substitution:
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); /*"* )
As @mas.morozov mentioned, you can use variadic macros:
#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;
})
}
You can play with it online here: https://godbolt.org/z/oLWV-z
I found that solution here: https://mort.coffee/home/obscure-c-features/
You can also make a more generic FOR_CONTAINER
macro:
#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;
})
}
Try it here: https://godbolt.org/z/9Gzqja
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With