[preprocessor] have macro do different things based on structure of its argument

Hello, I would like to write a macro MY_MACRO(x) that does different things based on the structure of its input, e.g. something different for each of the following forms: MY_MACRO(x) // a single token MY_MACRO((x, y)) // a parenthesized list of two tokens MY_MACRO((x, y, z)) // a parenthesized list of three tokens MY_MACRO(x y) // two tokens MY_MACRO(x y z) // three tokens MY_MACRO(x = y) // three tokens with the second one being something specific Are any of these possible? Thanks, Nate.

On 3/2/2011 4:11 AM, Nathan Ridge wrote:
Hello,
I would like to write a macro MY_MACRO(x) that does different things based on the structure of its input, e.g. something different for each of the following forms:
MY_MACRO(x) // a single token MY_MACRO((x, y)) // a parenthesized list of two tokens MY_MACRO((x, y, z)) // a parenthesized list of three tokens MY_MACRO(x y) // two tokens MY_MACRO(x y z) // three tokens MY_MACRO(x = y) // three tokens with the second one being something specific
Are any of these possible?
I will assume your examples are numbered from 1 to 6. In numbers 2 and 3 the parameter is a pp-lib tuple. Normally you would have to know in advance how many elements are in a tuple but if your compiler supports variadic macros you can use my variadic_macro_data library in the sandbox to know how many elements are in the pp-lib tuple and then you can subsequently extract any one of them. Numbers 1,4,5,6 are single elements. There is no way of which I know to determine how many space separated sequences of text there are in each element or extract any one of them. But there is a way to check whether the sequence starts with a given sequence, and you may be able to work from there via Lorenzo Caminiti's clever example, which he worked out for his Local library: "NOTE: This is more of a curiosity because for my application I can manipulate the storage classifiers using preprocessor metaprogramming. In fact, `auto` and `register` are known alphanumeric tokens (i.e., keywords) that always appear at the beginning of the parameter type expression so the following macros can be used to manipulate them: #include <boost/preprocessor.hpp> #include <boost/preprocessor/detail/is_unary.hpp> #define IS_AUTO_auto (1) /* must expand to unary */ #define IS_AUTO(tokens) BOOST_PP_IS_UNARY(BOOST_PP_CAT(IS_AUTO_, tokens)) #define REMOVE_AUTO_STRIP_auto /* must expand to nothing */ #define REMOVE_AUTO_(tokens) BOOST_PP_CAT(REMOVE_AUTO_STRIP_, tokens) #define REMOVE_AUTO(tokens) \ BOOST_PP_IIF(IS_AUTO(tokens), \ REMOVE_AUTO_ \ , \ tokens BOOST_PP_TUPLE_EAT(1) \ )(tokens) #define ADD_AUTO(tokens) \ BOOST_PP_EXPR_IIF(BOOST_PP_NOT(IS_AUTO(tokens)), auto) tokens IS_AUTO(auto int x) // 1 IS_AUTO(int x) // 0 REMOVE_AUTO(auto int x) // int x REMOVE_AUTO(int x) // int x ADD_AUTO(auto int x) // auto int x ADD_AUTO(int x) // auto int x (These macros work as long as the type expression starts with an alphanumeric token -- if not, I can wrap the type expression using Boost.Local's `BOOST_IDENTITY_TYPE` as in `BOOST_IDENITY_TYPE(::std::string) s`.)"

From: eldiener@tropicsoft.com
MY_MACRO(x) // a single token MY_MACRO((x, y)) // a parenthesized list of two tokens MY_MACRO((x, y, z)) // a parenthesized list of three tokens MY_MACRO(x y) // two tokens MY_MACRO(x y z) // three tokens MY_MACRO(x = y) // three tokens with the second one being something specific
I will assume your examples are numbered from 1 to 6.
In numbers 2 and 3 the parameter is a pp-lib tuple. Normally you would have to know in advance how many elements are in a tuple but if your compiler supports variadic macros you can use my variadic_macro_data library in the sandbox to know how many elements are in the pp-lib tuple and then you can subsequently extract any one of them.
Numbers 1,4,5,6 are single elements. There is no way of which I know to determine how many space separated sequences of text there are in each element or extract any one of them. But there is a way to check whether the sequence starts with a given sequence, and you may be able to work from there via Lorenzo Caminiti's clever example, which he worked out for his Local library:
"NOTE: This is more of a curiosity because for my application I can manipulate the storage classifiers using preprocessor metaprogramming. In fact, `auto` and `register` are known alphanumeric tokens (i.e., keywords) that always appear at the beginning of the parameter type expression so the following macros can be used to manipulate them:
[snip]
REMOVE_AUTO(auto int x) // int x REMOVE_AUTO(int x) // int x
ADD_AUTO(auto int x) // auto int x ADD_AUTO(int x) // auto int x
Interesting. I'm trying to do something slightly similar. I'm trying to accept both "typename identifier" and "identifier", and add "auto" (the C++0x kind) if there is no typename. So "ADD_AUTO(int x)" would remain "int x", but ADD_AUTO(x) would become "auto x". Do you think that's possible? Thanks, Nate.

On 3/2/2011 4:38 PM, Nathan Ridge wrote:
From: eldiener@tropicsoft.com
MY_MACRO(x) // a single token MY_MACRO((x, y)) // a parenthesized list of two tokens MY_MACRO((x, y, z)) // a parenthesized list of three tokens MY_MACRO(x y) // two tokens MY_MACRO(x y z) // three tokens MY_MACRO(x = y) // three tokens with the second one being something specific
I will assume your examples are numbered from 1 to 6.
In numbers 2 and 3 the parameter is a pp-lib tuple. Normally you would have to know in advance how many elements are in a tuple but if your compiler supports variadic macros you can use my variadic_macro_data library in the sandbox to know how many elements are in the pp-lib tuple and then you can subsequently extract any one of them.
Numbers 1,4,5,6 are single elements. There is no way of which I know to determine how many space separated sequences of text there are in each element or extract any one of them. But there is a way to check whether the sequence starts with a given sequence, and you may be able to work from there via Lorenzo Caminiti's clever example, which he worked out for his Local library:
"NOTE: This is more of a curiosity because for my application I can manipulate the storage classifiers using preprocessor metaprogramming. In fact, `auto` and `register` are known alphanumeric tokens (i.e., keywords) that always appear at the beginning of the parameter type expression so the following macros can be used to manipulate them:
[snip]
REMOVE_AUTO(auto int x) // int x REMOVE_AUTO(int x) // int x
ADD_AUTO(auto int x) // auto int x ADD_AUTO(int x) // auto int x
Interesting. I'm trying to do something slightly similar. I'm trying to accept both "typename identifier" and "identifier", and add "auto" (the C++0x kind) if there is no typename.
So "ADD_AUTO(int x)" would remain "int x", but ADD_AUTO(x) would become "auto x".
Do you think that's possible?
I would think you would have to know each type on which you want that to work, but you should be able to do that using Lorenzo's code as a basis. Essentially if you know the beginning text you should be able to work with the rest in the same way that Lorenzo shows.
participants (2)
-
Edward Diener
-
Nathan Ridge