Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++98

Function templates or preprocessor defines: what to choose?

2.89/5 (7 votes)
28 Aug 2017CPOL2 min read 12.8K   20  
A few words about function templates

Introduction

A few words about how compiler treats function templates. It could help you to choose between function templates and defines. But it also could be confused. Because there are also no one recipe for all tasks. 

Background

Firstly I received same results on with g++ compiler under linux and cygwin. Then after some comments I was planned to change the article, but I've some procrastination issues and I also fount out that I could repeat my results in some special cases.

Using the code

Sometime you might need to choose between old and famous #define directives and a murky templates magic. When you have to make this choice - you need to remember that templates compiled when they are required - so you will not get any memory saving advantaged by using them, but compiler can help you when you will try to use incompatible types. At the other hand you may save some more memory for something usefull by using #define directives.

Code below show two equivalents (full source file attached to this tip):

C++
//
#ifndef    _USE_DEFINES_
#define    FIELD_SEP    ","
template< class T > void convertField(const NullInd_e* pInd, const T* pField, size_t idx)
{
    if(pInd[idx]!=eNull)
        std::cout << pField[idx];
    else
        std::cout << ' ';
    std::cout << FIELD_SEP;
}
#else
#define    FIELD_SEP    "|"
#define    convertField(_N_,_F_,_I_)    if(_N_[_I_]!=eNull) \
    std::cout << _F_[_I_]; \
    else \
        std::cout << ' '; \
    std::cout << FIELD_SEP;
#endif
//

And when it was compiled with _USE_DEFINES_ a smaller executable file was produced, it ran faster and with less memory required. So, let's continue with the tests.

I compiled my source code with the command lines:

  • for template-based version: g++ def_templ.cpp -o def_templ
  • for define-based version: g++ def_templ.cpp -D_USE_DEFINES_ -o def_def
  • Project and source code for the Microsoft Visual Studio 2017 are attached as a separate archive

And here are the results:

  • Linux <server name> 3.10.0-123.el7.x86_64 #1 SMP Wed Jul 9 18:59:11 PDT 2014 x86_64 x86_64 x86_64 GNU/Linux + gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11):
    • ls -l def_*
      -rwxr-xr-x 1 <user> <group> 13907 Aug 28 10:36 def_def
      -rwxr-xr-x 1 <user> <group> 14093 Aug 28 10:36 def_templ

       

    • time ./def_def
                  | |            | |            | |
                 0| | 0.000985395| |   178803790| |          0178803790
                  | |            | |            | |
         379337186| |    0.364602| |   392261992| |  379337186392261992
                  | |            | |            | |
         198207689| |    0.487217| | -2032592072| | 198207689-203259207
                  | |            | |            | |
         975888346| |    0.233178| |  -724596254| | 975888346-724596254
                  | |            | |            | |
        2000878121| |     0.56806| | -1906560325| | 2000878121-19065603
      
      real    0m0.002s
      user    0m0.002s
      sys     0m0.001s

       

    • time ./def_templ
                  , ,            , ,            , ,
                 0, , 0.000985395, ,   178803790, ,          0178803790
                  , ,            , ,            , ,
         379337186, ,    0.364602, ,   392261992, ,  379337186392261992
                  , ,            , ,            , ,
         198207689, ,    0.487217, , -2032592072, , 198207689-203259207
                  , ,            , ,            , ,
         975888346, ,    0.233178, ,  -724596254, , 975888346-724596254
                  , ,            , ,            , ,
        2000878121, ,     0.56806, , -1906560325, , 2000878121-19065603
      
      real    0m0.002s
      user    0m0.001s
      sys     0m0.001s

       

  • CYGWIN_NT-6.1 <server name> 2.8.2(0.313/5/3) 2017-07-12 10:58 x86_64 Cygwin + gcc (GCC) 5.4.0
    • ls -l def_*
      -rwxrwxr-x+ 1 <user>       <group> 69029 Aug 28 14:34 def_def.exe
      -rwxrwxr-x+ 1 <user>       <group> 69923 Aug 28 14:34 def_templ.exe

       

    • time ./def_def
                  | |            | |            | |
         851401618| |    0.840485| |  1517566982| | 8514016181517566982
                  | |            | |            | |
         959030623| |    0.318693| |  3807181130| | 9590306233807181130
                  | |            | |            | |
          33463914| |     0.58409| |   684483038| |   33463914684483038
                  | |            | |            | |
         824023566| |    0.691004| |   252797108| |  824023566252797108
                  | |            | |            | |
        1932422408| |    0.163546| |   683206901| | 1932422408683206901
      
      real    0m0.170s
      user    0m0.000s
      sys     0m0.015s

       

    • time ./def_templ
                  , ,            , ,            , ,
         851401618, ,    0.840485, ,  1517566982, , 8514016181517566982
                  , ,            , ,            , ,
         959030623, ,    0.318693, ,  3807181130, , 9590306233807181130
                  , ,            , ,            , ,
          33463914, ,     0.58409, ,   684483038, ,   33463914684483038
                  , ,            , ,            , ,
         824023566, ,    0.691004, ,   252797108, ,  824023566252797108
                  , ,            , ,            , ,
        1932422408, ,    0.163546, ,   683206901, , 1932422408683206901
      
      real    0m0.130s
      user    0m0.015s
      sys     0m0.000s

       

  • FreeBSD <server name> 9.3-RELEASE-p43 FreeBSD 9.3-RELEASE-p43 #0: Sat May 28 00:15:23 UTC 2016 + gcc (GCC) 4.2.1 20070831 patched [FreeBSD]
    • ls -l def_*
      -rwxr-xr-x  1 <user>  <group>  9555 Aug 28 14:40 def_def
      -rwxr-xr-x  1 <user>  <group>  9857 Aug 28 14:40 def_templ

       

    • time ./def_def
                | |            | |            | |
       851401618| |    0.840485| |  1517566982| | 8514016181517566982
                | |            | |            | |
       959030623| |    0.318693| |  -487786166| | 959030623-487786166
                | |            | |            | |
        33463914| |     0.58409| |   684483038| |   33463914684483038
                | |            | |            | |
       824023566| |    0.691004| |   252797108| |  824023566252797108
                | |            | |            | |
      1932422408| |    0.163546| |   683206901| | 1932422408683206901
            0.04 real         0.00 user         0.00 sys
      
    • time ./def_templ
                , ,            , ,            , ,
       851401618, ,    0.840485, ,  1517566982, , 8514016181517566982
                , ,            , ,            , ,
       959030623, ,    0.318693, ,  -487786166, , 959030623-487786166
                , ,            , ,            , ,
        33463914, ,     0.58409, ,   684483038, ,   33463914684483038
                , ,            , ,            , ,
       824023566, ,    0.691004, ,   252797108, ,  824023566252797108
                , ,            , ,            , ,
      1932422408, ,    0.163546, ,   683206901, , 1932422408683206901
            0.06 real         0.01 user         0.00 sys
      
  • Microsoft Visual C++ 2017 (x64) - cygwin was running on the same machine
    • dir def_*.exe
      28.08.2017  14:49            17 408 def_def.exe
      28.08.2017  14:48            17 408 def_templ.exe
    • def_def.exe
                  | |            | |            | |
                41| |    0.563585| |        6334| |              416334
                  | |            | |            | |
             26500| |    0.585009| |       15724| |          2650015724
                  | |            | |            | |
             11478| |    0.895962| |       26962| |          1147826962
                  | |            | |            | |
             24464| |    0.174108| |       28145| |          2446428145
                  | |            | |            | |
             23281| |    0.513535| |        9961| |           232819961
      Run time: 0 seconds 15 milliseconds
    • def_templ.exe
                  , ,            , ,            , ,
                41, ,    0.563585, ,        6334, ,              416334
                  , ,            , ,            , ,
             26500, ,    0.585009, ,       15724, ,          2650015724
                  , ,            , ,            , ,
             11478, ,    0.895962, ,       26962, ,          1147826962
                  , ,            , ,            , ,
             24464, ,    0.174108, ,       28145, ,          2446428145
                  , ,            , ,            , ,
             23281, ,    0.513535, ,        9961, ,           232819961
      Run time: 0 seconds 16 milliseconds

As far as we could see from the latest tests the Linux results caught from a rather new GCC and the Cygwin results from a newest GCC show that defines are worser than templates. Otherwise oldest GCC and newest Visual C++ show that define is better than templates. So it could be a default optimisation issue of the aged compilators and the default optimisation has been changed recently (since december 2016 when the results were more homogeneous.

Points of Interest

IMHO: All technology must be used in apropriate way.

History

December 2016 - Initial draft and source code

August 2017 - Second edition with tests results

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)