CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Apr 2001
    Posts
    10

    Function templates are better than macros?

    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

  2. #2
    Join Date
    Oct 2002
    Location
    UK
    Posts
    3
    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;
    }
    Try to relax and enjoy the crisis... (Ashleigh Brilliant)

  3. #3
    Join Date
    Jun 2002
    Posts
    1,417
    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.

  4. #4
    Join Date
    Oct 2002
    Location
    UK
    Posts
    3
    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
    Try to relax and enjoy the crisis... (Ashleigh Brilliant)

  5. #5
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470
    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.
    Code:
    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.
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  6. #6
    Join Date
    Oct 2002
    Location
    UK
    Posts
    3
    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.
    Try to relax and enjoy the crisis... (Ashleigh Brilliant)

  7. #7
    Join Date
    Apr 1999
    Location
    Altrincham, England
    Posts
    4,470
    Yes, I looked it up later and there is a sequence point after the left-hand expression, so that particular example is OK. However
    Code:
    i++ + i++;
    most definitely is not OK. So, a macro:
    Code:
    #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
    Code:
    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).
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.
    --
    Sutter and Alexandrescu, C++ Coding Standards

    Programs must be written for people to read, and only incidentally for machines to execute.

    --
    Harold Abelson and Gerald Jay Sussman

    The cheapest, fastest and most reliable components of a computer system are those that aren't there.
    -- Gordon Bell


  8. #8
    Join Date
    Jun 2002
    Location
    Letchworth, UK
    Posts
    1,020
    "Function templates are better alternatives than using macros".

    Can anybody please tell me how?
    Take the following
    Code:
    // 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
    Code:
    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
    Code:
    a = 5;
    b = 10;
    mswap(a,b)+100;
    results in a = 10, b = 105. Templates won't let you do silly things like that.
    Succinct is verbose for terse

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured