Boost logo

Boost Users :

Subject: Re: [Boost-users] [preprocessor] have macro do different things based on structure of its argument
From: Edward Diener (eldiener_at_[hidden])
Date: 2011-03-02 15:59:33


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`.)"


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net