In addition to the explanations posted by others in the comments, you should also be aware of side effects in macros when an argument is evaluated more than once during macro expansion.
In the case of the usual C-style definition of MIN(x,y) (for example, as indicated by @Boann), note that x, y expand twice . Your original definition extends x and y twice three times. Before reaching the points of sequence and short circuit evaluation, let's just say that the results can be unpredictable, to say the least (and may even vary depending on the compiler). This is one of the reasons many C ++ programmers believe that preprocessor macros are evil.
To see this in action, try both definitions with MIN(x++, y++) . For an even more evil possibility, we consider the case
result = MIN( x, ShouldOnlyBeCalledOnce_BecauseThisFunctionHasSideEffects(y));
While the preprocessor still has its place (and there are things you can do with it that just cannot be done in any other way), in particular, C ++ is usually a good idea to determine what represents whether the preprocessor solution is in itself.
For example: when overloaded, the C ++ implementation initially gave us things like
int min(int x, int y) { return (x < y) ? x : y); } some_other_type min(some_other_type x, some_other_type y) { return (x < y) ? x : y; }
The templates gave us much more, as in:
template <class T> const T& min (const T& a, const T& b) { return !(b < a) ? a : b; }
Convenience of the macro, but without the side effects that may occur when the parameter is expanded more than once. By the way, if you are wondering why the test !( b < a) ? a : b; !( b < a) ? a : b; compared to (a < b) ? a : b; (a < b) ? a : b; , this is because if (a == b) , a must be returned and because it is less than the only relation that needs to be defined for a given type to support a wide range of containers (among other things).