MACRO and template with two ( or more ) parameters

S

swellfr

Hi

if have simple macro defined this way:
#define M_OPplus( classname ) typedef classname operator+(const
classname& rhs);

and a template class :
template<typename X, typename Y>
class Test1
{
public:
double run();
M_OPplus( Test1<X,Y> )
};
The compiler (VS2003) is complaining : warning C4002: too many actual
parameters for macro, . I think it is related to the comma in the
middle , the preprocessor may think that i am passing two parameters
to the macro.

Is it possible to fix it and does it conform with the C++ standart?

Many Thx
 
B

Barry

Hi

if have simple macro defined this way:
#define M_OPplus( classname ) typedef classname operator+(const
classname& rhs);

and a template class :
template<typename X, typename Y>
class Test1
{
public:
double run();
M_OPplus( Test1<X,Y> )
^

the comma split up your argument into to parts

write
 
C

Chris Thomasson

if have simple macro defined this way:
#define M_OPplus( classname ) typedef classname operator+(const
classname& rhs);

and a template class :
template<typename X, typename Y>
class Test1
{
public:
double run();
M_OPplus( Test1<X,Y> )
};
The compiler (VS2003) is complaining : warning C4002: too many actual
parameters for macro, . I think it is related to the comma in the
middle , the preprocessor may think that i am passing two parameters
to the macro.

Your correct.

Is it possible to fix it and does it conform with the C++ standart?

Yes. You can use a little trick that involves passing a name of a macro
function to the M_OPplus macro which calls it to get at the tokens.
Something like this:


#define M_OPplus(classname_macro) \
typedef classname_macro() \
operator+(const classname_macro()& rhs)


template<typename X, typename Y>
class Test1 {
#define M_Test1() Test1<X,Y>
public:
double run();
M_OPplus(M_Test1);
};


See what I am getting at here?
 
C

Chris Thomasson

Barry said:
(e-mail address removed) wrote: [...]
the comma split up your argument into to parts

write
M_OPplus(( Test1<X,Y> ))

[...]

That introduces extra parenthesis which can muck up syntax. For instance:


This has a syntax error:
_______________
#define M_OPplus(classname) \
typedef classname \
operator+(const classname &rhs)

template<typename X, typename Y>
class Test1 {
public:
double run();
M_OPplus((Test1<X,Y>));
};
_______________



This does not:
_______________
#define M_OPplus(classname_macro) \
typedef classname_macro() \
operator+(const classname_macro()& rhs)

template<typename X, typename Y>
class Test1 {
#define M_Test1() Test1<X,Y>
public:
double run();
M_OPplus(M_Test1);
};
_______________
 
B

Barry

Chris said:
Barry said:
(e-mail address removed) wrote: [...]
the comma split up your argument into to parts

write
M_OPplus(( Test1<X,Y> ))

[...]

That introduces extra parenthesis which can muck up syntax. For instance:


This has a syntax error:
_______________
#define M_OPplus(classname) \
typedef classname \
operator+(const classname &rhs)

template<typename X, typename Y>
class Test1 {
public:
double run();
M_OPplus((Test1<X,Y>));
};
_______________



This does not:
_______________
#define M_OPplus(classname_macro) \
typedef classname_macro() \
operator+(const classname_macro()& rhs)

template<typename X, typename Y>
class Test1 {
#define M_Test1() Test1<X,Y>
public:
double run();
M_OPplus(M_Test1);
};
_______________

yeh, you are right,
didn't carefully view the context
 
B

Barry

Chris said:
Your correct.



Yes. You can use a little trick that involves passing a name of a macro
function to the M_OPplus macro which calls it to get at the tokens.
Something like this:


#define M_OPplus(classname_macro) \
typedef classname_macro() \
operator+(const classname_macro()& rhs)


template<typename X, typename Y>
class Test1 {
#define M_Test1() Test1<X,Y>
#define M_Test1 ....

definition and invocation should be identical
 
C

Chris Thomasson

Barry said:
Chris Thomasson wrote: [...]
#define M_OPplus(classname_macro) \
typedef classname_macro() \
operator+(const classname_macro()& rhs)

template<typename X, typename Y>
class Test1 {
#define M_Test1() Test1<X,Y>
#define M_Test1 ....

definition and invocation should be identical

[...]

I am not exactly sure what you mean here. Are you suggesting that 'M_Test1'
does not really need to be a macro function? Well, in that case the code
would need to be modified to something like:

____________
#define M_OPplus(classname) \
typedef classname \
operator+(const classname &rhs)

template<typename X, typename Y>
class Test1 {
#define M_Test1 Test1<X,Y>
public:
double run();
M_OPplus(M_Test1);
};
____________


At first glance I thought that the 'M_Test1' macro would be expanded and
then passed to 'M_OPplus' which would produce the original error that the OP
was asking about. After I compiled it (gcc) I realized that it was getting
expanded in the context of the 'M_OPplus'.

I guess the only drawback from this would be that you could not pass the
'classname' parameter to another similar macro function. For instance:


this does not compile:
____________
#define M_Typedef(classname) \
typedef classname

#define M_OPplus(classname) \
M_Typedef(classname) \
operator+(const classname &rhs)

template<typename X, typename Y>
class Test1 {
#define M_Test1 Test1<X,Y>
public:
double run();
M_OPplus(M_Test1);
};

____________



while this does:
____________
#define M_Typedef(classname_macro) \
typedef classname_macro()

#define M_OPplus(classname_macro) \
M_Typedef(classname_macro) \
operator+(const classname_macro()& rhs)

template<typename X, typename Y>
class Test1 {
#define M_Test1() Test1<X,Y>
public:
double run();
M_OPplus(M_Test1);
};
____________


So I guess defining 'M_Test1' as a macro function instead of a plain macro
is more "flexible".


Any thoughts?
 
B

Barry

Chris said:
Barry said:
Chris Thomasson wrote: [...]
#define M_OPplus(classname_macro) \
typedef classname_macro() \
operator+(const classname_macro()& rhs)

template<typename X, typename Y>
class Test1 {
#define M_Test1() Test1<X,Y>
#define M_Test1 ....

definition and invocation should be identical

[...]

I am not exactly sure what you mean here. Are you suggesting that
'M_Test1' does not really need to be a macro function? Well, in that
case the code would need to be modified to something like:


I mean if you
#define M_Test1() ...
then call
M_Test1() other than M_Test1

if you
#define M_Test1 ...
then call
M_Test1 other than M_Test1()
 
C

Chris Thomasson

Barry said:
Chris said:
Barry said:
Chris Thomasson wrote:
[...]
I am not exactly sure what you mean here. Are you suggesting that
'M_Test1' does not really need to be a macro function? Well, in that case
the code would need to be modified to something like:
[...]

I mean if you
#define M_Test1() ...
then call
M_Test1() other than M_Test1

Well, as soon as I call M_Test1() it will expand on the spot. I want to be
able to delay expansion until the exact place I need it. Therefore, I can
use the _name_ of the macro function M_Test1 as a sort-of function pointer.
This is the "trick" I mentioned to the OP...


Here is an example program you can compile:
_______________
#include <cstdio>

#define CALL_MACRO_FUNCTION(func_ptr)func_ptr()

#define MY_MESSAGE() "Press <ENTER> to exit."

int main(void) {
puts(CALL_MACRO_FUNCTION(MY_MESSAGE));
getchar();
return 0;
}

_______________


As far as I can tell, this is 100% legitimate, and conforms to the standard.

Does that make sense to you?
 
B

Barry

Chris said:
Barry said:
Chris Thomasson wrote: [...]
#define M_OPplus(classname_macro) \
typedef classname_macro() \
operator+(const classname_macro()& rhs)

template<typename X, typename Y>
class Test1 {
#define M_Test1() Test1<X,Y>
#define M_Test1 ....

definition and invocation should be identical

[...]

I am not exactly sure what you mean here. Are you suggesting that
'M_Test1' does not really need to be a macro function? Well, in that
case the code would need to be modified to something like:

____________
#define M_OPplus(classname) \
typedef classname \
operator+(const classname &rhs)

template<typename X, typename Y>
class Test1 {
#define M_Test1 Test1<X,Y>
public:
double run();
M_OPplus(M_Test1);
};
____________


At first glance I thought that the 'M_Test1' macro would be expanded and
then passed to 'M_OPplus' which would produce the original error that
the OP was asking about. After I compiled it (gcc) I realized that it
was getting expanded in the context of the 'M_OPplus'.

I guess the only drawback from this would be that you could not pass the
'classname' parameter to another similar macro function. For instance:


this does not compile:
____________
#define M_Typedef(classname) \
typedef classname

#define M_OPplus(classname) \
M_Typedef(classname) \
operator+(const classname &rhs)

template<typename X, typename Y>
class Test1 {
#define M_Test1 Test1<X,Y>
public:
double run();
M_OPplus(M_Test1);
};

____________



while this does:
____________
#define M_Typedef(classname_macro) \
typedef classname_macro()

#define M_OPplus(classname_macro) \
M_Typedef(classname_macro) \
operator+(const classname_macro()& rhs)

template<typename X, typename Y>
class Test1 {
#define M_Test1() Test1<X,Y>
public:
double run();
M_OPplus(M_Test1);
};
____________


So I guess defining 'M_Test1' as a macro function instead of a plain
macro is more "flexible".

Well, forgive my English

You know

#define SOME_MACRO()

int main()
{
SOME_MACRO();
SOME_MACRO; // does not compile
}

so IMHO,
the definition and invoking of macro should better give the same form.
 
B

Barry

Chris said:
Barry said:
Chris Thomasson wrote: [...]
You know

#define SOME_MACRO()

int main()
{
SOME_MACRO();
SOME_MACRO; // does not compile
}
[...]

Your correct that it does not compile. However this does compile:

____________
#define CALL_IT(func_ptr)func_ptr()
#define SOME_MACRO()

int main(){
SOME_MACRO();
CALL_IT(SOME_MACRO);
return 0;
}

____________


See what I am getting at here?


I think I have to learn more about macro first.
thanks for your patience
 
C

Chris Thomasson

Barry said:
Chris Thomasson wrote: [...]
You know

#define SOME_MACRO()

int main()
{
SOME_MACRO();
SOME_MACRO; // does not compile
}
[...]

Your correct that it does not compile. However this does compile:

____________
#define CALL_IT(func_ptr)func_ptr()
#define SOME_MACRO()

int main(){
SOME_MACRO();
CALL_IT(SOME_MACRO);
return 0;
}

____________


See what I am getting at here?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,228
Members
46,818
Latest member
SapanaCarpetStudio

Latest Threads

Top