How can i generate variadic macro for concatenate string - c++

I got stuck here...
#define CONCAT(a,b) BOOST_PP_STRINGIZE(BOOST_PP_CAT(a,b))#define CONCAT1(a,b,c) CONCAT(CONCAT(a,b),c) and so on. How i can to generate the CONCAT macro even if 20 arguments? May be i can to use BOOST_PP_SEQ_FOR_EACH but i don't understand how to do it?

It depends on you use-case.
This
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#define SEQ (a)(b)(c)
BOOST_PP_STRINGIZE(BOOST_PP_SEQ_CAT(SEQ)) // "abc"
will concatenate the sequence and then stringize it. It is also possible to simply stringize each argument as "a" "b" "c" is equivalent to "abc".
#define MY_STRINGIZE(r, data, elem) BOOST_PP_STRINGIZE(elem)
BOOST_PP_SEQ_FOR_EACH(MY_STRINGIZE, _, SEQ)

As you are already using the Boost libraries, try BOOST_PP_SEQ_CAT (documentation). It takes a list of elements and simply concatenates them together, i.e. BOOST_PP_SEQ_CAT(a b c)
results in abc.

Related

Preprocessor initialize array

How, if necessary, using boost preprocessor, initialize the array as follows:
INIT_ARRAY(plus,minus)
//extract to
std::array<std::pair<char const *,std::string>, 2> array{{
{"plus", std::string("plus")}, {"minus", std::string("minus")} }};
INIT_ARRAY(plus,minus,multiply)
//extract to
std::array<std::pair<char const *,std::string>, 3> array{{
{"plus", std::string("plus")}, {"minus", std::string("minus")}, {"multiply", std::string("multiply")} }};
P.S. Couldn't solve the problem with the last comma in the initializer (...{n-1} , {n} ,)
and counting the number of arguments to pass to std::array<...,n>. I use the preprocessor, since the names passed to the macro will be used later for code generation. Used c++20
You can use BOOST_PP_COMMA_IF for conditional commas, and BOOST_PP_VARIADIC_SIZE to work out the size beforehand.
This should work (for non-empty arrays):
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/variadic/size.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>
#define INIT_ARRAY_INITIALIZER(r, _, i, e) BOOST_PP_COMMA_IF(i) {BOOST_PP_STRINGIZE(e), std::string(BOOST_PP_STRINGIZE(e))}
#define INIT_ARRAY(...) \
std::array<std::pair<char const *, std::string>, \
BOOST_PP_VARIADIC_SIZE(__VA_ARGS__)> array{{ \
BOOST_PP_SEQ_FOR_EACH_I(INIT_ARRAY_INITIALIZER, _, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
}};

Can macro variadic parameters being expanded?

I have a lot of custom attributes (by using clang annotate, if you ask), and it is annoying to write
__attribute(a)__ __attribute(b)__ __attribute(c)__ int i;
can I design a macro,for example MyAttr(...),
if I use MyAttr(a,b,c), it will expand to __attribute(a)__ __attribute(b)__ __attribute(c)__?
It can be done with boost.preprocessor, something like this:
#include <boost/preprocessor.hpp>
#define ATTRIBUTE(r, _, elem) __attribute__((elem))
#define ATTRIBUTES(seq) BOOST_PP_SEQ_FOR_EACH(ATTRIBUTE, _, seq)
ATTRIBUTES((a)(b)(c)(d)) // expands to __attribute__((a)) __attribute__((b)) __attribute__((c)) __attribute__((d))

Is it possible to pass one argument to macro and get out two?

I'm trying to write some functions as macros, but I just can't figure it out how to do it.
#define PA0 (PORTA, PIN0_bm);
#define PA1 (PORTA, PIN1_bm);
...
#define PA7 (PORTA, PIN7_bm);
#define PD0 (PORTD, PIN0_bm);
#define PD1 (PORTD, PIN1_bm);
...
#define PD7 (PORTD, PIN7_bm);
then macro for function
#define pinMode(x) (x[0].DIRSET = x[1])
which I wanted to look like after preprocessor
pinMode(PA0) -> (PORTA.DIRSET = PIN0_bm)
After compiling (AVR-gcc) I'm getting invalid types 'int[int]' for array subscript error.
Is it possible to pass one argument to macro and get out two?
C++ macros end on the next newline, so the semicolons are being expanded, too. As originally suggested by Mooing Duck:
#JakobJug: Why not have the macros the other way around? #define pinmode(L,R) (L[0].DIRSET=R[1]) and then #define PA0 pinmode(PORTA,PIN0_bm)?
Except it needs a small correction, giving #define pinmode(L,R) (L.DIRSET=R). Then PA0 expands to pinmode(PORTA,PIN0_bm) and then (PORTA.DIRSET=PIN0_bm).

C++ preprocessor add word if condition

I'm writing a library that uses the preprocessor meta-programming Boost.Preprocessor. One macro looks kind of like this:
#define MY_MACRO(my_type) return some_function<my_type>()
Now, the problem is that I need to remove the return if my_type is void. I checked Boost.Preprocessor, but I didn't see anything that could help me. How do I accomplish this? Something like:
#define MY_MACRO(my_type) BOOST_PP_IF(\
TYPE_EQUALS(my_type,void),return,BOOST_PP_EMPTY()) some_function<my_type>()
Unfortunately, boost preprocessor doesn't have an easy way to compare two tokens. Of course for your case you may just need to use some simple detection. This should work on C99 preprocessors:
#define CHECK_N(x, n, ...) n
#define CHECK(...) CHECK_N(__VA_ARGS__, 0,)
#define PROBE(x) x, 1,
#define IS_VOID(x) CHECK(BOOST_PP_CAT(IS_VOID_, x))
#define IS_VOID_void PROBE(~)
However, this won't work for parenthesis, for varidiac data(such as types with commas in them), or pointers. So here are the ones that work and don't work:
IS_VOID(int) // 0
IS_VOID(void) // 1
IS_VOID((void)) // Compile error
IS_VOID(std::map<int, int>) // Compile error
IS_VOID(void*) // Returns 1, but should return 0
You could try to work around all these cases or you could use a more general comparison macro(like the one here):
#define IS_PAREN(x) CHECK(IS_PAREN_PROBE x)
#define IS_PAREN_PROBE(...) PROBE(~)
#define IS_COMPARABLE(x) IS_PAREN( CAT(COMPARE_, x) (()) )
#define NOT_EQUAL(x, y) \
IIF(BITAND(IS_COMPARABLE(x))(IS_COMPARABLE(y)) ) \
( \
PRIMITIVE_COMPARE, \
1 EAT \
))(x, y)
#define EQUAL(x, y) COMPL(NOT_EQUAL(x, y))
#define COMPARE_void(x) x
#define IS_VOID(x) EQUAL(x, void)
Which could be updated to use boost preprocessor components. This should work for more cases, but still won't work with parenthesis(which may not be a problem).
Finally, this is just a comparison on the textual level, so if the user has typedefed void, it will incorrectly return false:
typedef void my_void;
IS_VOID(my_void) // Returns 0
If you are using the detection technique, you could allow the user to extend it for user-defined voids, like so:
#define IS_VOID(x) CHECK(BOOST_PP_CAT(IS_VOID_, x))
#define IS_VOID_void PROBE(~)
// User-defined void
#define IS_VOID_my_void PROBE(~)

Macro increase value and then concatenate

I want to create a recursive Macro the will create the "next" class.
Example:
#define PRINTME(indexNum) class m_##(indexNum+1) { }
The indexNum + 1 is evaluated as an int, and won't concatenate to the class name.
How can I cause the compiler to evaluate that, before concatenating?
If you want to generate unique class names every time the PRINTME is invoked then, following is one way:
#define CONCATE1(X,Y) X##Y
#define CONCATE(X,Y) CONCATE1(X,Y)
#define PRINTME class CONCATE(m_,__COUNTER__) {}
__COUNTER__ is an extension in gcc and I am not sure if it's present in other compilers. It's guaranteed that compiler will add 1 every time this macro is invoked.
(In this case, you cannot use __LINE__ or __FILE__ effectively.)
Demo.
The simple answer is that you can't. The preprocessor generally deals in text and tokens; the only place arithmetic is carried out in in #if and #elif directives.
Also, macro expansion isn't recursive. During expansion, the macro being expanded is disabled, and is not available for further substitution.
Well it is doable, based on your motivation and ability to endure ugly code. First off define increment macro:
#define PLUS_ONE(x) PLUS_ONE_##x
#define PLUS_ONE_0 1
#define PLUS_ONE_1 2
#define PLUS_ONE_2 3
#define PLUS_ONE_3 4
#define PLUS_ONE_4 5
#define PLUS_ONE_5 6
#define PLUS_ONE_7 8
#define PLUS_ONE_8 9
#define PLUS_ONE_9 10
// and so on...
You can't just use PLUS_ONE(x) in concatenation operation, since preprocessor won't expand it. There is a way, however - you can abuse the fact that the preprocessor expands variadic arguments.
// pass to variadic macro to expand an argument
#define PRINTME(indexNum) PRINTME_PRIMITIVE(PLUS_ONE(indexNum))
// do concatenation
#define PRINTME_PRIMITIVE(...) class m_ ## __VA_ARGS__ { }
Done!
PRINTME(1); // expands to class m_2 { };
Have you considered using templates instead?