Click here to Skip to main content
15,885,028 members
Articles / Programming Languages / C++98
Tip/Trick

Function templates or preprocessor defines: what to choose?

Rate me:
Please Sign up or sign in to vote.
2.89/5 (7 votes)
28 Aug 2017CPOL2 min read 12.1K   4   9
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)


Written By
Software Developer (Senior) NetCracker
Russian Federation Russian Federation
I came to the industry at the end of that times when the computer program executes as it was written. I saw a quite big machines, occupied more than 100 square meters for its central processor, but I started my professional activity as a programmer on IBM PC clones. There were different CPU architectures (68k, PowerPC, 386/486, SPARC...) when I began, but Intel defeated them all with Pentium CPU (marketing) family.
I saw the knowledge and technology fragmentation. I saw many technologies started, developed and retired. However, I have not seen many things yet.
I have some experience, but my experience is not perfectly comprehensive. I still have many things to learn and I still cannot make a poker face when I find out some aspects about how the things were designed and works. My experience does not make me an absolute expert in some areas, because these areas are changing. I know some things, but I also understand that some things I know could be useless for nowadays.

Comments and Discussions

 
QuestionYour conclusions Pin
Jochen Arndt28-Aug-17 4:17
professionalJochen Arndt28-Aug-17 4:17 
AnswerRe: Your conclusions Pin
Alexey Shtykov1-Nov-17 3:40
professionalAlexey Shtykov1-Nov-17 3:40 
Questionyou should make template inline Pin
augustheart4-Dec-16 14:33
augustheart4-Dec-16 14:33 
AnswerRe: you should make template inline Pin
Alexey Shtykov7-Dec-16 4:13
professionalAlexey Shtykov7-Dec-16 4:13 
GeneralRe: you should make template inline Pin
Rick York7-Dec-16 4:57
mveRick York7-Dec-16 4:57 
QuestionAlternative Pin
YvesDaoust2-Dec-16 2:13
YvesDaoust2-Dec-16 2:13 
I find appending line continuations on the macros terribly annoying, and you also lose the ability of the debugger to step in the code, which is a serious limitation.

My alternative is to code as usual in a .h file and substitute the would-be-template-arguments types and constants with identifiers. Like
C++
// File snippet.h
Type i= Const;

\#undef Type
\#undef Const

Then you instantiate with an include directive wherever you want.
C++
// File main.cpp
\#define Type int
\#define Const 4
\#include "snippet.h"

\#define Type float
\#define Const 3.14f
\#include "snippet.h"

The undefs are inserted in the include file for convenience.
AnswerRe: Alternative Pin
Alexey Shtykov7-Dec-16 4:52
professionalAlexey Shtykov7-Dec-16 4:52 
SuggestionThis is a good start Pin
Rick York1-Dec-16 4:57
mveRick York1-Dec-16 4:57 
GeneralRe: This is a good start Pin
Alexey Shtykov7-Dec-16 4:23
professionalAlexey Shtykov7-Dec-16 4:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.