By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,434 Members | 1,854 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,434 IT Pros & Developers. It's quick & easy.

converting C macros to templates

P: n/a
Hi,

I have several long complex C macros in the math module of aUCBLogo like

#define _XFUNC_primitive(NAME)\
NodeP _##NAME(PairPP arg)\
{ ((ObjectP)(arg[1]))->var()->NAME( arg[2] );\
return Unbound;\
}

which are hard to debug, and now I thought about changing them into
templates. Is this possible in principle?
Can please someone give me some hints,
because I can't figure out how to do the conversion?
Best would be a translation of my macro example into a template,
this would help me a lot.

Thanks,
Andreas

Nov 22 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a

Andreas Micheler wrote:
Hi,

I have several long complex C macros in the math module of aUCBLogo like

#define _XFUNC_primitive(NAME)\
NodeP _##NAME(PairPP arg)\
{ ((ObjectP)(arg[1]))->var()->NAME( arg[2] );\
return Unbound;\
}

which are hard to debug, and now I thought about changing them into
templates. Is this possible in principle?


It depends on what the macros do. Templates can do some things that
macros can't and vice versa.

One thing that's going on here is that the macro call can specify a
name, which is inserted into the expansion. The user writes
_XFUNC_primitive(foo) and the macro writes a function called _foo,
which calls through this argument array through a function pointer
called foo.

(Let's not discuss the clueless intrusions into forbidden symbol
namespaces; since you didn't write this).

Templates cannot be parametrized on identifiers. They can't generate
identifiers, or insert identifiers into code. If you write a template
function called foo, all of its expansions will be various overloads of
a function called foo. Moreover, you can't pass a parameter into the
template which will specify the name of a function to be called from
the body.

What you can do is write it as a template class instead: a class which
overloads operator (). Then you can make instances of that class, and
give those instances names. The indirection upon the function pointer
can be done using a pointer-to-member.

To do that, we make the template parameter a pointer-to-member, which
points to a function pointer:

Simplified example:

#include <cstddef>
#include <iostream>

using namespace std;

struct operations {
size_t (*read)(void *, size_t);
size_t (*write)(void *, size_t);
};

template <size_t (* operations::*func)(void *, size_t)>
class wrapper
{
public:
size_t operator()(operations *op, void *ptr, size_t size)
{
return (op->*func)(ptr, size);
}
};

size_t read_func(void *buf, size_t size)
{
cout << "read_func called on " << buf << " of size " << size <<
endl;
}

size_t write_func(void *buf, size_t size)
{
cout << "write_func called on " << buf << " of size " << size <<
endl;
}

int main()
{
unsigned char buf[256];

// table of operations
operations ops = { read_func, write_func };

// use the template to generate wrapper "functions" that call
indirect thorugh
// the operations structure

wrapper<&operations::read> read_wrapper;
wrapper<&operations::write> write_wrapper;

// call the read wrapper, on the given operations structure.
Control goes
// through read_wrapper object's operator (), which calls ops.read,

// ending up in read_func.

read_wrapper(&ops, buf, sizeof buf);
return 0;
}

Nov 22 '05 #2

P: n/a
Thanks, Kaz!

So the answer to my question is probably NO.

Kaz Kylheku wrote:
Andreas Micheler wrote:
Hi,

I have several long complex C macros in the math module of aUCBLogo like

#define _XFUNC_primitive(NAME)\
NodeP _##NAME(PairPP arg)\
{ ((ObjectP)(arg[1]))->var()->NAME( arg[2] );\
return Unbound;\
}

which are hard to debug, and now I thought about changing them into
templates. Is this possible in principle?


It depends on what the macros do. Templates can do some things that
macros can't and vice versa.

One thing that's going on here is that the macro call can specify a
name, which is inserted into the expansion. The user writes
_XFUNC_primitive(foo) and the macro writes a function called _foo,
which calls through this argument array through a function pointer
called foo.

(Let's not discuss the clueless intrusions into forbidden symbol
namespaces; since you didn't write this).

Templates cannot be parametrized on identifiers. They can't generate
identifiers, or insert identifiers into code. If you write a template
function called foo, all of its expansions will be various overloads of
a function called foo. Moreover, you can't pass a parameter into the
template which will specify the name of a function to be called from
the body.

What you can do is write it as a template class instead: a class which
overloads operator (). Then you can make instances of that class, and
give those instances names. The indirection upon the function pointer
can be done using a pointer-to-member.

To do that, we make the template parameter a pointer-to-member, which
points to a function pointer:

Simplified example:

#include <cstddef>
#include <iostream>

using namespace std;

struct operations {
size_t (*read)(void *, size_t);
size_t (*write)(void *, size_t);
};

template <size_t (* operations::*func)(void *, size_t)>
class wrapper
{
public:
size_t operator()(operations *op, void *ptr, size_t size)
{
return (op->*func)(ptr, size);
}
};

size_t read_func(void *buf, size_t size)
{
cout << "read_func called on " << buf << " of size " << size <<
endl;
}

size_t write_func(void *buf, size_t size)
{
cout << "write_func called on " << buf << " of size " << size <<
endl;
}

int main()
{
unsigned char buf[256];

// table of operations
operations ops = { read_func, write_func };

// use the template to generate wrapper "functions" that call
indirect thorugh
// the operations structure

wrapper<&operations::read> read_wrapper;
wrapper<&operations::write> write_wrapper;

// call the read wrapper, on the given operations structure.
Control goes
// through read_wrapper object's operator (), which calls ops.read,

// ending up in read_func.

read_wrapper(&ops, buf, sizeof buf);
return 0;
}


Nov 22 '05 #3

P: n/a
Andreas Micheler wrote:
Hi,

I have several long complex C macros in the math module of aUCBLogo like

#define _XFUNC_primitive(NAME)\
NodeP _##NAME(PairPP arg)\
{ ((ObjectP)(arg[1]))->var()->NAME( arg[2] );\
return Unbound;\
}


Well to start with the above snipped is invalid C++ because
of the misuse of the leading underscore.

The real question is what are you trying to accomplish. The
code with an C-style cast looks extremely dubious (and frankly
if ObjectP is Object*, I've never understood why people think
that sort of typedef makes more sense than saying Object*.)
Nov 22 '05 #4

P: n/a
Ron Natalie wrote:
Andreas Micheler wrote:
Hi,

I have several long complex C macros in the math module of aUCBLogo like

#define _XFUNC_primitive(NAME)\
NodeP _##NAME(PairPP arg)\
{ ((ObjectP)(arg[1]))->var()->NAME( arg[2] );\
return Unbound;\
}

Well to start with the above snipped is invalid C++ because
of the misuse of the leading underscore.


I never saw any problem with a leading underscore in MSVC5 or gcc.
The real question is what are you trying to accomplish. The
code with an C-style cast looks extremely dubious (and frankly
if ObjectP is Object*, I've never understood why people think
that sort of typedef makes more sense than saying Object*.)


I use ObjectP because I have written Ptr debug templates which implement
smart pointers (for bounds checking and to debug the garbage collector
of aUCBLogo). aUCBLogo is free and OpenSource (GPL), you easily find it
with google. So you can check out Math_.cpp if you have time.

The PairPP arg is the default function argument of a primitive in
aUCBLogo. It is because the arguments vary very much between different
primitives.

The code snipet is from the math module of aUCBLogo. It implements xAdd,
xSub, xMul and so on. There are about 1600 lines of such macro code in
aUCBLogo, because in the inner functions I use different code fragments
for the computation, of i.e. multiplication of Array's of some data
structures. It is the fastes way to do it, but if there were means to
convert the code to template code the debugging would be much easier.

Best Regards,
Andreas

Nov 22 '05 #5

P: n/a
In article <3u************@news.dfncis.de>,
Andreas Micheler <An**************@Student.Uni-Augsburg.de> wrote:
Ron Natalie wrote:
...
Well to start with the above snipped is invalid C++ because
of the misuse of the leading underscore.


I never saw any problem with a leading underscore in MSVC5 or gcc.


The you've just been lucky so far.

It's just as easy/hard not to do it, so best to just avoid it
so as to not bump heads with the rules, which basically says
those names are for the "compiler and library" implementor
(there are specific situations that should be avoided,
but I just avoid all _ prefixed names in my "end user code",
that is, where Comeau C++ is not involved).
--
Greg Comeau / Celebrating 20 years of Comeauity!
Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
Nov 22 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.