Click to See Complete Forum and Search --> : Function templates are better than macros?
newbie2001
October 15th, 2002, 06:55 AM
Hi All,
In one of the books i have read that "Function templates are better alternatives than using macros".
Can anybody please tell me how?
If possible, specify an example.
Though macros aren't type safe,is it possible to perform type checking on macros by any means?
Thanks in Advance
tel
October 15th, 2002, 10:19 AM
Macros can have their parameters evaluated more than once. For example the code below gives the output
max = 5
MAX = 6
templates also have the advantage that they have type checking.
I am not aware of any method of type checking on macro arguments.
[FONT=courier new]
// Example code illustrating the max function using
// 1. a template
// 2. a macro
#include <iostream>
template<typename T>
T max( T a, T b )
{
return( ( a > b ) ? a : b );
}
#define MAX(A,B) ((A>(B))?A:B)
int main()
{
int first = 3; int second = 4;
std::cout << "max = " << max( ++first, ++second ) << std::endl;
first = 3; second = 4;
std::cout << "MAX = " << MAX( ++first, ++second ) << std::endl;
return 0;
}
stober
October 15th, 2002, 11:57 AM
Originally posted by tel
// 1. a template
// 2. a macro
template<typename T>
T max( T a, T b )
{
return( ( a > b ) ? a : b );
}
#define MAX(A,B) ((A>(B))?A:B)
int main()
{
int first = 3; int second = 4;
std::cout << "max = " << max( ++first, ++second ) << std::endl;
first = 3; second = 4;
std::cout << "MAX = " << MAX( ++first, ++second ) << std::endl;
return 0;
}
Using these examples, the macro may produce the wrong results because it is expanded like this:
( ++first > ++second) ? ++first : ++second;
I'm not sure, but I do not think the template will behave that way.
tel
October 16th, 2002, 04:03 AM
The template will not behave the same way as the macro.
On compilation, the compiler will generate a function from the template that takes two ints as arguments and returns an int. ie. it will create the function
int max( int a, int b )
{
return( ( a > b ) ? a : b );
}
The increments on the arguments to the function will only be evaluated once - on calling the function hence first takes the value 4 and second becomes 5 so max returns 5.
As you correctly said, the macro will be expanded within the code giving:
( ++first > ++second ) ? ++first : ++second;
Thus which ever is the larger of the two ints will be incremented a second time. i.e. max returns 6.
Note that after the call to max:
The template gives first = 4 and second = 5
The macro gives first = 4 and second = 6
Graham
October 16th, 2002, 04:29 AM
Originally posted by tel
( ++first > ++second ) ? ++first : ++second;
Thus which ever is the larger of the two ints will be incremented a second time. i.e. max returns 6.
Note also that assigning to the same entity between two sequence points is undefined behaviour. e.g.
i = ++a + ++a;
is undefined, since a is incremented twice before reaching the end of the statement.
AFAIK, the ternary operator does not introduce a sequence point, so the above macro expansion may also be undefined.
tel
October 16th, 2002, 06:31 AM
The ternary operator evaluates the conditional and at that point, any side effects of it occur.
Then only one of the two expressions is evaluated along with respective side effects.
This means that the results of both the macro and template are defined.
Graham
October 16th, 2002, 07:32 AM
Yes, I looked it up later and there is a sequence point after the left-hand expression, so that particular example is OK. However
i++ + i++;
most definitely is not OK. So, a macro:
#define SELF_ADD(x) (x) + (x)
...
int i = 1;
int j = SELF_ADD(i++);
is ill-formed and has an unpredicatable result (j could be 2 or 3 depending on exactly when the compiler inserts the increment), whereas
inline int self_add(int x)
{
return x + x;
}
...
int i = 1;
int j = self_add(i++);
is well-formed and has a predictable result (j == 2 and i == 2).
cup
October 16th, 2002, 11:06 AM
"Function templates are better alternatives than using macros".
Can anybody please tell me how?
Take the following
// assume t is defined somewhere
#define mswap(a,b) \
t = a; \
a = b; \
b = t
template <class KLASS> tswap(KLASS& a, KLASS& b)
{
KLASS t;
t = a;
a = b;
b = t;
}
Ignoring the temporary variable, mswap and tswap basically do the same thing. However, when you have to step through it in the debugger, what you will see with the macro is just
mswap(a,b);
The debugger will stay there for 3 steps and the move on to the next statement. At this point, some people give up and ask "why isn't the debugger working". With templates, most debuggers will actually step into the template code so you can see where it is going wrong, if it does go wrong.
With a bit of trickery, you can also do some very unsavoury things with macros. eg
a = 5;
b = 10;
mswap(a,b)+100;
results in a = 10, b = 105. Templates won't let you do silly things like that.
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.