Thread: Macro vs (inline) template function

  1. #1
    Registered User
    Join Date
    May 2008
    Location
    Paris
    Posts
    248

    Macro vs (inline) template function

    Hi there (2) !

    In my project, I've seen people preferring macros to template functions for performance enhancement (e.g., min/max functions).

    Is this true? I know that copy-constructor elision already fairly optimises these simple function calls.

    Further, can the said-to-be lack of performance be enhanced by the rvalue-reference in the new standard? This will further reduce the copy-constructor call when using the temporary return value as argument in another function.

    Thanks a lot in advance!

    Mark

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I'd expect a very poor compiler to do poorly on both, and a good compiler to do well on both - a template inline like this:
    Code:
    template<typename T>
    inline T max(T x, T y)
    {
         return (x > y)?x:y;
    }
    to produce identical code to:
    Code:
    #define MAX(x, y)  (((x) > (y)) ? (x) : (y))
    with the exception that things like MAX(++x, ++y) will behave strangely.

    Have you actually looked at the code generated by the compiler with high optimization settings?

    What are the objects you are comparing - basic types (e.g int, float, double) or classes with complex comparison rules (e.g. std::string, std::complex)

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    ++matsp

    When there is a choice, I only use macros when I have to target a simple compiler.

    Soma

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by matsp View Post
    I'd expect a very poor compiler to do poorly on both, and a good compiler to do well on both - a template inline like this:
    Code:
    template<typename T>
    inline T max(T x, T y)
    {
         return (x > y)?x:y;
    }
    To veer a little bit, what are people's opinions on the above? Should such a function use ">" or ">=" for the comparison?

    I usually use ">=", because in the case of equality, it seems to make sense that the first argument should have primacy.

    On the other hand, this leads to inconsistency when you write the corresponding min() function, because if a == b, then max(a, b) will return a, but min(a, b) will return b.

    Just something to think about. Obviously, none of this matters if you're dealing with numeric values, but for objects with comparison operators you could potentially have side effects based on the implementation.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Actually I prefer

    return b<a?a:b;

    b is only returned when it is indeed more than a. I don't see potential side effects but people are welcome to prove me wrong.

  6. #6
    The larch
    Join Date
    May 2006
    Posts
    3,573
    All standard algorithms that are about ordering of things only use operator<. This is the minimum requirement to make an object comparable for ordering. Providing operator> or operator>= is entirely optional.

    I believe it is also customary to pass template arguments by reference (since they can be expensive to copy), and in case of max it might also return by reference. (But then one might expect it to be inlined anyway.)
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  7. #7
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    I'm with anon. There's a lot of lazy programmers that need a comparison function to work with their class, so they just implement operator< without implementing the others. So if you use < you're more likely to work with code written by those people.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Right, my code was more to show the principle than any attempt to be portable, correct and a good example to follow.

    I'm not very familiar with STL, as the embedded OS that I use at work, whilst using C++, has no STL at all, and it uses very little template code (it is for embedded systems, so it is important to keep the code-size small).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by anon View Post
    All standard algorithms that are about ordering of things only use operator<. This is the minimum requirement to make an object comparable for ordering. Providing operator> or operator>= is entirely optional.

    I believe it is also customary to pass template arguments by reference (since they can be expensive to copy), and in case of max it might also return by reference. (But then one might expect it to be inlined anyway.)
    Yes, but we're not talking about operator<() specifically, we're talking about min and max. If neither "a < b" nor "b < a" is true, then should min(a, b) return the same value as max(a, b)?

    Or to think another way, you might expect that min(a, b) == -max(-a, -b), but depending on the implementation, this may not be the case. (Where '==' means object identity (same object), not equality)
    Last edited by brewbuck; 03-03-2009 at 07:08 PM.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Or to think another way, you might expect that min(a, b) == -max(-a, -b), but depending on the implementation, this may not be the case. (Where '==' means object identity (same object), not equality)
    Only in the sense that the thing named a is an alias for b.

    Every C programmer knows it's a mistake to rely on p == b for a lexicographical comparison of C-strings, but it's an example of what you're talking about. It doesn't matter what min(p, b) results in though since there is no ultimate difference between the two if they are the same object.

    I guess what I mean to say is I can't think of a situation where >= blows up, but I respect your being cautious about it, if that makes sense.

  11. #11
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by brewbuck View Post
    Yes, but we're not talking about operator<() specifically, we're talking about min and max. If neither "a < b" nor "b < a" is true, then should min(a, b) return the same value as max(a, b)?
    Without looking at the standard library code, yes I believe it should, hence:
    Code:
    template<typename T>
    inline T min(T x, T y)
    {
         return (y < x) ? y : x;
    }
    
    template<typename T>
    inline T max(T x, T y)
    {
         return (y < x) ? x : y;
    }
    Uses only less-than, and min(x, y) and max(x, y) will return different items when x and y are equivalent.
    Of course if you want it to return the same one from both, simply switch all the x's and y's in one of those functions
    Last edited by iMalc; 03-04-2009 at 12:45 AM.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  12. #12
    The larch
    Join Date
    May 2006
    Posts
    3,573
    There's a lot of lazy programmers that need a comparison function to work with their class, so they just implement operator< without implementing the others. So if you use < you're more likely to work with code written by those people.
    I don't work with anybodies code... I wouldn't call this pure laziness either. It is very important to know that the STL works entirely in terms of "less-than" for ordering, even if you provide your own comparison objects. Otherwise, you'd have to look up the documentation each time to see in which terms a particular algorithm is implemented in (should the user defined function model "less-than", "greater-than", "greater-than-or-equal" etc?).

    If I'm not mistaken

    Code:
    a >= b <--> !(a < b)
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

  13. #13
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    You could also use the Boost operators library to fill in all the operators that you're missing. Then you could implement operator< and have Boost do the rest. But since you're writing the comparison function rather than the objects being compared, just do what most people would expect and write it in relation to operator< and re-order the comparisons to return a if a & b are equivalent.
    "I am probably the laziest programmer on the planet, a fact with which anyone who has ever seen my code will agree." - esbo, 11/15/2008

    "the internet is a scary place to be thats why i dont use it much." - billet, 03/17/2010

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by cpjust
    You could also use the Boost operators library to fill in all the operators that you're missing.
    In this case of operator< (and also for operator==) the functions provided by <utility> in the std::rel_ops namespace are likely to suffice.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. template function argument deduce
    By George2 in forum C++ Programming
    Replies: 2
    Last Post: 03-11-2008, 08:56 PM
  2. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  3. error: template with C linkage
    By michaels-r in forum C++ Programming
    Replies: 3
    Last Post: 05-17-2006, 08:11 AM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  5. I need help with passing pointers in function calls
    By vien_mti in forum C Programming
    Replies: 3
    Last Post: 04-24-2002, 10:00 AM