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):
#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