Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

macro dispatching(overloading)

239 views
Skip to first unread message

tongjunhui

unread,
Jan 1, 2010, 10:56:01 AM1/1/10
to
Hi

I want to dispatch a macro call according to the argument count.

consider I have these macros:
#define DO(x) /* some code here */
#define DO(x1,x2) /* some code here */
#define DO(x1,x2,x3) /* some code here */
This won't compile because macro overloading is not allowed.

I must use the followig code:
#define DO1(x) /* some code here */
#define DO2(x1,x2) /* some code here */
#define DO3(x1,x2,x3) /* some code here */
when I use them, I must manually select which macro to use according to
the arguments. e.g. DO3(2,3,4) this is a bit redundent because the
compiler *do* know which 'DO' can be select and would warn if I select
the wrong version e.g. DO2(2,3,4). That's a bit ugly.

When variadic macro comes I thought my quesion are solved via the
following code:
#define DO(...) CONCAT(DO, __VA_ARGC__)(__VA_ARGV__)
the idea behind is using DO(...) to forward the macro call according to
the arguments. e.g. DO(1,2,3) will be expanded to DO3(1,2,3). BUT
unfortunately there isn't something like '__VA_ARGC__'.

There isn't something like '__VA_ARGC__', omg.

Is there other way to dispatch macro call according to the argument count?

Thanks a lot

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Francis Glassborow

unread,
Jan 1, 2010, 5:51:27 PM1/1/10
to
tongjunhui wrote:
> Hi
>
> I want to dispatch a macro call according to the argument count.
>
> consider I have these macros:
> #define DO(x) /* some code here */
> #define DO(x1,x2) /* some code here */
> #define DO(x1,x2,x3) /* some code here */
> This won't compile because macro overloading is not allowed.

The puzzle for me is why you want to use the preprocessor here at all.
Why not simply overload an inline function which is the way to do this
if you do not need C compatibility.

LR

unread,
Jan 2, 2010, 2:28:26 AM1/2/10
to
Francis Glassborow wrote:
> tongjunhui wrote:
>> Hi
>>
>> I want to dispatch a macro call according to the argument count.
>>
>> consider I have these macros:
>> #define DO(x) /* some code here */
>> #define DO(x1,x2) /* some code here */
>> #define DO(x1,x2,x3) /* some code here */
>> This won't compile because macro overloading is not allowed.
>
> The puzzle for me is why you want to use the preprocessor here at all.
> Why not simply overload an inline function which is the way to do this
> if you do not need C compatibility.
>

The OP doesn't show what /* some code here */ is. I suppose it's
possible the OP might want to do something like:

#define DO(x) for(unsigned int i=0; i<x; i++)
#define DO(x1,x2) for(unsigned int i=x1; i<x2; i++)
#define DO(x1,x2,x3) for(unsigned int i=x1; i<x2; i+=x3)

I'm not sure how an inline function could be used for this functionality.

Tongjunhui, can you please tell us what /* some code here */ is?

LR

Tony Delroy

unread,
Jan 2, 2010, 2:32:26 AM1/2/10
to
On Jan 2, 7:51 am, Francis Glassborow
<francis.glassbo...@btinternet.com> wrote:

> tongjunhui wrote:
> > #define DO(x) /* some code here */
> > #define DO(x1,x2) /* some code here */
> > #define DO(x1,x2,x3) /* some code here */
> > This won't compile because macro overloading is not allowed.
>
> The puzzle for me is why you want to use the preprocessor here at all.
> Why not simply overload an inline function which is the way to do this
> if you do not need C compatibility.

Good to avoid macros when you can, but the preprocessor can do things
that inline functions can't (e.g. stringify arguments, generate a
sequence of string literals that the compiler can consolidate into
one, pack comma-separated values with additional values in an array,
merge elements together to create identifiers, pass arbitrary code
snippets even if too incomplete to create a functor representation,
get the caller's location ala __FILE__, __LINE__, __func__,...), so
there are certainly reasons to be interested in the preprocessor.

Re tongjunhui's question: you can typically use the macro to generate
whatever value-adds warrant the preprocessor's use (vs a function, as
discussed above), then pass the value-adds alongside the macro
arguments (i.e. __VA_ARGS__) to an overloaded function, or convert the
list of arguments into a representation that can be passed as a single
function argument (i.e. by overloading the comma operator, or using
GNU statement expressions for an array initialisation / not as if
variadic macros are portable/compliant anyway...).

Cheers,
Tony

tongjunhui

unread,
Jan 2, 2010, 2:56:51 AM1/2/10
to
于 2010/1/2 6:51, Francis Glassborow 写道:
> tongjunhui wrote:
>> Hi
>>
>> I want to dispatch a macro call according to the argument count.
>>
>> consider I have these macros:
>> #define DO(x) /* some code here */
>> #define DO(x1,x2) /* some code here */
>> #define DO(x1,x2,x3) /* some code here */
>> This won't compile because macro overloading is not allowed.
>
> The puzzle for me is why you want to use the preprocessor here at all.
> Why not simply overload an inline function which is the way to do this
> if you do not need C compatibility.
>
OK, below is a more reasonable example, but a little more complex.
to implement a macro auto executing satements on block leave:
#define ON_LEAVE(statement) \
struct leave_helper{ \
~leave_helper() { statement; } \
} lh__;
if we use ON_LEAVE(printf("func leave")) in some function, "func leave"
will be printed when function exit(caused by the destructor of the
object lh__), no matter what reason cause the exiting. (return, throw, etc.)
this macro seems be capable to used as a very general RAII tool, like:
ON_LEAVE(fclose(fp))
ON_LEAVE(closesocket(sock))
ON_LEAVE(domyfree(x,y,z,w))
but wait, local class (the struct leave_helper) *cannot* see function's
local variable. we must pass the varible as parameters, like this:
#define ON_LEAVE(statement, type, var) \
struct leave_helper { \
type var; \
leave_helper(type v):var(v){} \
~leave_helper(}{statement)} \
} lh__;
it can be used like this: ON_LEAVE(fclose(fp), FILE*, fp),
ON_LEAVE(closesocket(sock), SOCKET, sock)

but what about more parameters? current solution is implementing a
series macros like ON_LEAVE:
#define ON_LEAVE_2(statement, t1, v1, t2, v2) ...
#define ON_LEAVE_3(statement, t1, v1, t2, v2, t3, v3) ...
etc..

that's my problem in real world. The key point here is that I can make
brand new temp class with MACRO, write some code in it's destructor, but
inline function cannot.

LR

unread,
Jan 3, 2010, 5:15:33 PM1/3/10
to
Stefan Ram wrote:
> #include <iostream> /* ::std::cout */
> #include <ostream> /* << */
>
> #define ONLEAVE(x) for(int onleave_=1;onleave_;((onleave_=0),(x)))
>
> int main()
> { ::std::cout << "alpha" << '\n';
> ONLEAVE( ::std::cout << "beta" << '\n' )
> ONLEAVE( ::std::cout << "gamma" << '\n' )
> ONLEAVE( ::std::cout << "delta" << '\n' )
> ::std::cout << "epsilon" << '\n'; }
>

And elsethread Stefan Ram wrote:
> when the block is left by certains means such as exceptions.
>
> But I also believe that you have not yet understood what I
> do with the �for�. You should be able to see this by reading
> the sequence of greek letter names in the source code and
> comparing this sequence with their sequence in ::std::cout,
> which is given below the source code in my previous post.


That's clever but, as your elsethread reply implies, I think it's a
little difficult to understand. I know that I had trouble reading it.
Also,if someone adds a statement after ::std::cout << "epsilon" <<
'\n'; such as ::std::cout << "out of order" << '\n'; things don't happen
the way one might expect.

However, if we can get the OP to go along with having one variable per
struct, then perhaps something like this:

#include <iostream>
#include <string>

#define LEAVE_STRUCT(classname,varname,statement,type,var,arg)\
struct classname {\
type var;\
classname##(type va) : var(va) {}\
~##classname##() { statement; }\
} varname##(arg);

#define CLASS_NAME3(x,y) x##y
#define CLASS_NAME2(x,y) CLASS_NAME3(x,y)
#define CLASS_NAME CLASS_NAME2(leave,__LINE__)

#define VAR_NAME3(x,y) x##y##_
#define VAR_NAME2(x,y) VAR_NAME3(x,y)
#define VAR_NAME VAR_NAME2(lh,__LINE__)

#define LEAVE(statement,type,var,arg)\
LEAVE_STRUCT(CLASS_NAME,VAR_NAME,statement,type,var,arg)

void q() {
std::cout << "A" << std::endl;
LEAVE(std::cout<<x<<std::endl,int,x,72)
LEAVE(std::cout<<x<<std::endl,std::string,x,"bye bye")
std::cout << "B" << std::endl;
}

int main() {
q();
char c;
std::cin >> c;
}

I can't say that I think it's pretty, and I wonder if there's a nicer
way to do it. Maybe using templates? If not, then I wonder if we (by
'we' I don't really mean to include me) shouldn't want to revisit the
preprocessor someday and give it a few better features.

I ran into problems compiling this in debug. I understand there are
some compiler settings for that, but I just used release. However, I
also tried compiling at http://www.comeaucomputing.com/tryitout/ and
didn't get any warnings or errors. I don't know if the code is fully
compliant.

Doing some reading about this on the web, I picked up some tricks here:
http://www.decompile.com/cpp/faq/file_and_line_error_string.htm and
here: http://okmij.org/ftp/cpp-digest/Functional-Cpp.html I also got
some ideas from reading parts of my compiler's docs.


LR

Tony Delroy

unread,
Jan 4, 2010, 10:19:31 AM1/4/10
to
On Jan 2, 4:56 pm, tongjunhui <tongjun...@gmail.com> wrote:
> to implement a macro auto executing satements on block leave:
> #define ON_LEAVE(statement) \
> struct leave_helper{ \
> ~leave_helper() { statement; } \
> } lh__;
> ...

If that's what you're after, you might want to check out boost's Scope
Exit facilities (also macros).

Cheers,
Tony

Jyoti Sharma

unread,
Jan 5, 2010, 2:17:09 PM1/5/10
to

"tongjunhui" <tongj...@gmail.com> wrote in message
news:hhjr1l$8bh$1...@speranza.aioe.org...

> Hi
>
> I want to dispatch a macro call according to the argument count.
>
> consider I have these macros:
> #define DO(x) /* some code here */
> #define DO(x1,x2) /* some code here */
> #define DO(x1,x2,x3) /* some code here */
> This won't compile because macro overloading is not allowed.
>
> I must use the followig code:
> #define DO1(x) /* some code here */
> #define DO2(x1,x2) /* some code here */
> #define DO3(x1,x2,x3) /* some code here */
> when I use them, I must manually select which macro to use according to
> the arguments. e.g. DO3(2,3,4) this is a bit redundent because the
> compiler *do* know which 'DO' can be select and would warn if I select the
> wrong version e.g. DO2(2,3,4). That's a bit ugly.
>
> When variadic macro comes I thought my quesion are solved via the
> following code:
> #define DO(...) CONCAT(DO, __VA_ARGC__)(__VA_ARGV__)
> the idea behind is using DO(...) to forward the macro call according to
> the arguments. e.g. DO(1,2,3) will be expanded to DO3(1,2,3). BUT
> unfortunately there isn't something like '__VA_ARGC__'.
>
> There isn't something like '__VA_ARGC__', omg.
>
> Is there other way to dispatch macro call according to the argument count?
>

compiler does not touch macros. It is the preprocessor. Probably if you look
hard you will find a better way to do whatever you are trying to do. One
very crude way to achieve what you want in macros would be to use
stringizing preprocessor directives with macros. Where one macros creates a
string that will result into another specific macro name. But I wonder about
its utility. You would always know while writing the macros how many
arguments it is taking... or am I wrong? So you can actually do with
different name for each one I suppose?


Regards,
Jyoti

roman.pe...@gmail.com

unread,
Feb 2, 2010, 3:26:45 PM2/2/10
to
On 1 Jan, 16:56, tongjunhui <tongjun...@gmail.com> wrote:
> There isn't something like '__VA_ARGC__', omg.

See this thread for the implementation of __VA_ARGC__:
http://groups.google.com/group/comp.std.c/browse_thread/thread/77ee8c8f92e4a3fb/346fc464319b1ee5

Roman Perepelitsa.

0 new messages