aaragon wrote:

Hi everyone. A very simple question. I would like to know what is

better in terms of performance. I want to use a simple function to

obtain the minimum of two values. One way could be using a macro:

#define min(a,b) ((a<b)?a:b)

Wait a minute, you have not yet been bitten by the macro bug.

If you are going to use the macro, you need to change it to:

#define min(a,b) ((a)<(b)?(a):(b))

Precedence of the "<" operator can be higher that other operators and

you could be evaluating something different to what you expect.

>

I thought that another way could be to use a template function:

template <class T>

T min<T a, T b>

{

if(a < b)

return a;

else

return b;

}

The problem with this is you're passing in copies. If it is a non

trivial type you could be incurring an overhead.

template <class T>

const T & min<const T & a, const T & b>

{

if(a < b)

return a;

else

return b;

}

The problem with this is that it won't work for different types, e.g.

min(1,0.2) will fail to find a match with the min() above.

So you can change it to:

template <class T1, class T2>

T1 min<const T1 & a, const T2 & b>

{

if(a < b)

return a;

else

return b;

}

OK - now you have a problem with promotion of the return value.

min(1,0.1) returns 0, not 0.1.

What type should the return type be ? See the lengthy "Promote" class

below that will help you work it out.

template <class T1, class T2>

typename Promote<T1,T2>::type min<const T1 & a, const T2 & b>

{

if(a < b)

return a;

else

return b;

}

This will do what you expect it to do. As for efficiency, the compiler

can quite easily optimize this, inline it or whatever.

>

Any ideas on which way is better to implement? I guess that whenever I

use the template function is going to help me check at compile time.

The biggest problem with using using macros is when you do things like:

int x = min(++y,x--);

If you use a macro, you're sol because you have a problem.

Also, for some reason I don't like using macros. Thank you.

I think I have posted this one before. If c++ had a "typeof", we could

do away with this nonsense.

// ======== Promote ===============================================

/**

* This template allows you to determine the type that the compiler

* will promote an arithmetic expression to.

*/

template <typename T1, typename T2>

struct Promote

{

};

// the same types are the same ! cool

// this should also make POD types work

template <typename T1>

struct Promote<T1,T1>

{

typedef T1 type;

};

// specify all the type promotions ...

template <struct Promote<unsigned char,char{ typedef int type; };

template <struct Promote<signed char,char{ typedef int type; };

template <struct Promote<short,char{ typedef int type; };

template <struct Promote<unsigned short,char{ typedef int type; };

template <struct Promote<int,char{ typedef int type; };

template <struct Promote<unsigned int,char{ typedef unsigned int

type; };

template <struct Promote<long,char{ typedef long type; };

template <struct Promote<unsigned long,char{ typedef unsigned long

type; };

template <struct Promote<long long,char{ typedef long long type; };

template <struct Promote<unsigned long long,char{ typedef unsigned

long long type; };

template <struct Promote<float,char{ typedef float type; };

template <struct Promote<double,char{ typedef double type; };

template <struct Promote<long double,char{ typedef long double type; };

template <struct Promote<char,unsigned char{ typedef int type; };

template <struct Promote<signed char,unsigned char{ typedef int type; };

template <struct Promote<short,unsigned char{ typedef int type; };

template <struct Promote<unsigned short,unsigned char{ typedef int

type; };

template <struct Promote<int,unsigned char{ typedef int type; };

template <struct Promote<unsigned int,unsigned char{ typedef

unsigned int type; };

template <struct Promote<long,unsigned char{ typedef long type; };

template <struct Promote<unsigned long,unsigned char{ typedef

unsigned long type; };

template <struct Promote<long long,unsigned char{ typedef long long

type; };

template <struct Promote<unsigned long long,unsigned char{ typedef

unsigned long long type; };

template <struct Promote<float,unsigned char{ typedef float type; };

template <struct Promote<double,unsigned char{ typedef double type; };

template <struct Promote<long double,unsigned char{ typedef long

double type; };

template <struct Promote<char,signed char{ typedef int type; };

template <struct Promote<unsigned char,signed char{ typedef int type; };

template <struct Promote<short,signed char{ typedef int type; };

template <struct Promote<unsigned short,signed char{ typedef int

type; };

template <struct Promote<int,signed char{ typedef int type; };

template <struct Promote<unsigned int,signed char{ typedef unsigned

int type; };

template <struct Promote<long,signed char{ typedef long type; };

template <struct Promote<unsigned long,signed char{ typedef unsigned

long type; };

template <struct Promote<long long,signed char{ typedef long long

type; };

template <struct Promote<unsigned long long,signed char{ typedef

unsigned long long type; };

template <struct Promote<float,signed char{ typedef float type; };

template <struct Promote<double,signed char{ typedef double type; };

template <struct Promote<long double,signed char{ typedef long

double type; };

template <struct Promote<char,short{ typedef int type; };

template <struct Promote<unsigned char,short{ typedef int type; };

template <struct Promote<signed char,short{ typedef int type; };

template <struct Promote<unsigned short,short{ typedef int type; };

template <struct Promote<int,short{ typedef int type; };

template <struct Promote<unsigned int,short{ typedef unsigned int

type; };

template <struct Promote<long,short{ typedef long type; };

template <struct Promote<unsigned long,short{ typedef unsigned long

type; };

template <struct Promote<long long,short{ typedef long long type; };

template <struct Promote<unsigned long long,short{ typedef unsigned

long long type; };

template <struct Promote<float,short{ typedef float type; };

template <struct Promote<double,short{ typedef double type; };

template <struct Promote<long double,short{ typedef long double type; };

template <struct Promote<char,unsigned short{ typedef int type; };

template <struct Promote<unsigned char,unsigned short{ typedef int

type; };

template <struct Promote<signed char,unsigned short{ typedef int

type; };

template <struct Promote<short,unsigned short{ typedef int type; };

template <struct Promote<int,unsigned short{ typedef int type; };

template <struct Promote<unsigned int,unsigned short{ typedef

unsigned int type; };

template <struct Promote<long,unsigned short{ typedef long type; };

template <struct Promote<unsigned long,unsigned short{ typedef

unsigned long type; };

template <struct Promote<long long,unsigned short{ typedef long long

type; };

template <struct Promote<unsigned long long,unsigned short{ typedef

unsigned long long type; };

template <struct Promote<float,unsigned short{ typedef float type; };

template <struct Promote<double,unsigned short{ typedef double type; };

template <struct Promote<long double,unsigned short{ typedef long

double type; };

template <struct Promote<char,int{ typedef int type; };

template <struct Promote<unsigned char,int{ typedef int type; };

template <struct Promote<signed char,int{ typedef int type; };

template <struct Promote<short,int{ typedef int type; };

template <struct Promote<unsigned short,int{ typedef int type; };

template <struct Promote<unsigned int,int{ typedef unsigned int type; };

template <struct Promote<long,int{ typedef long type; };

template <struct Promote<unsigned long,int{ typedef unsigned long

type; };

template <struct Promote<long long,int{ typedef long long type; };

template <struct Promote<unsigned long long,int{ typedef unsigned

long long type; };

template <struct Promote<float,int{ typedef float type; };

template <struct Promote<double,int{ typedef double type; };

template <struct Promote<long double,int{ typedef long double type; };

template <struct Promote<char,unsigned int{ typedef unsigned int

type; };

template <struct Promote<unsigned char,unsigned int{ typedef

unsigned int type; };

template <struct Promote<signed char,unsigned int{ typedef unsigned

int type; };

template <struct Promote<short,unsigned int{ typedef unsigned int

type; };

template <struct Promote<unsigned short,unsigned int{ typedef

unsigned int type; };

template <struct Promote<int,unsigned int{ typedef unsigned int type; };

template <struct Promote<long,unsigned int{ typedef unsigned long

type; };

template <struct Promote<unsigned long,unsigned int{ typedef

unsigned long type; };

template <struct Promote<long long,unsigned int{ typedef long long

type; };

template <struct Promote<unsigned long long,unsigned int{ typedef

unsigned long long type; };

template <struct Promote<float,unsigned int{ typedef float type; };

template <struct Promote<double,unsigned int{ typedef double type; };

template <struct Promote<long double,unsigned int{ typedef long

double type; };

template <struct Promote<char,long{ typedef long type; };

template <struct Promote<unsigned char,long{ typedef long type; };

template <struct Promote<signed char,long{ typedef long type; };

template <struct Promote<short,long{ typedef long type; };

template <struct Promote<unsigned short,long{ typedef long type; };

template <struct Promote<int,long{ typedef long type; };

template <struct Promote<unsigned int,long{ typedef unsigned long

type; };

template <struct Promote<unsigned long,long{ typedef unsigned long

type; };

template <struct Promote<long long,long{ typedef long long type; };

template <struct Promote<unsigned long long,long{ typedef unsigned

long long type; };

template <struct Promote<float,long{ typedef float type; };

template <struct Promote<double,long{ typedef double type; };

template <struct Promote<long double,long{ typedef long double type; };

template <struct Promote<char,unsigned long{ typedef unsigned long

type; };

template <struct Promote<unsigned char,unsigned long{ typedef

unsigned long type; };

template <struct Promote<signed char,unsigned long{ typedef unsigned

long type; };

template <struct Promote<short,unsigned long{ typedef unsigned long

type; };

template <struct Promote<unsigned short,unsigned long{ typedef

unsigned long type; };

template <struct Promote<int,unsigned long{ typedef unsigned long

type; };

template <struct Promote<unsigned int,unsigned long{ typedef

unsigned long type; };

template <struct Promote<long,unsigned long{ typedef unsigned long

type; };

template <struct Promote<long long,unsigned long{ typedef long long

type; };

template <struct Promote<unsigned long long,unsigned long{ typedef

unsigned long long type; };

template <struct Promote<float,unsigned long{ typedef float type; };

template <struct Promote<double,unsigned long{ typedef double type; };

template <struct Promote<long double,unsigned long{ typedef long

double type; };

template <struct Promote<char,long long{ typedef long long type; };

template <struct Promote<unsigned char,long long{ typedef long long

type; };

template <struct Promote<signed char,long long{ typedef long long

type; };

template <struct Promote<short,long long{ typedef long long type; };

template <struct Promote<unsigned short,long long{ typedef long long

type; };

template <struct Promote<int,long long{ typedef long long type; };

template <struct Promote<unsigned int,long long{ typedef long long

type; };

template <struct Promote<long,long long{ typedef long long type; };

template <struct Promote<unsigned long,long long{ typedef long long

type; };

template <struct Promote<unsigned long long,long long{ typedef

unsigned long long type; };

template <struct Promote<float,long long{ typedef float type; };

template <struct Promote<double,long long{ typedef double type; };

template <struct Promote<long double,long long{ typedef long double

type; };

template <struct Promote<char,unsigned long long{ typedef unsigned

long long type; };

template <struct Promote<unsigned char,unsigned long long{ typedef

unsigned long long type; };

template <struct Promote<signed char,unsigned long long{ typedef

unsigned long long type; };

template <struct Promote<short,unsigned long long{ typedef unsigned

long long type; };

template <struct Promote<unsigned short,unsigned long long{ typedef

unsigned long long type; };

template <struct Promote<int,unsigned long long{ typedef unsigned

long long type; };

template <struct Promote<unsigned int,unsigned long long{ typedef

unsigned long long type; };

template <struct Promote<long,unsigned long long{ typedef unsigned

long long type; };

template <struct Promote<unsigned long,unsigned long long{ typedef

unsigned long long type; };

template <struct Promote<long long,unsigned long long{ typedef

unsigned long long type; };

template <struct Promote<float,unsigned long long{ typedef float

type; };

template <struct Promote<double,unsigned long long{ typedef double

type; };

template <struct Promote<long double,unsigned long long{ typedef

long double type; };

template <struct Promote<char,float{ typedef float type; };

template <struct Promote<unsigned char,float{ typedef float type; };

template <struct Promote<signed char,float{ typedef float type; };

template <struct Promote<short,float{ typedef float type; };

template <struct Promote<unsigned short,float{ typedef float type; };

template <struct Promote<int,float{ typedef float type; };

template <struct Promote<unsigned int,float{ typedef float type; };

template <struct Promote<long,float{ typedef float type; };

template <struct Promote<unsigned long,float{ typedef float type; };

template <struct Promote<long long,float{ typedef float type; };

template <struct Promote<unsigned long long,float{ typedef float

type; };

template <struct Promote<double,float{ typedef double type; };

template <struct Promote<long double,float{ typedef long double type; };

template <struct Promote<char,double{ typedef double type; };

template <struct Promote<unsigned char,double{ typedef double type; };

template <struct Promote<signed char,double{ typedef double type; };

template <struct Promote<short,double{ typedef double type; };

template <struct Promote<unsigned short,double{ typedef double type; };

template <struct Promote<int,double{ typedef double type; };

template <struct Promote<unsigned int,double{ typedef double type; };

template <struct Promote<long,double{ typedef double type; };

template <struct Promote<unsigned long,double{ typedef double type; };

template <struct Promote<long long,double{ typedef double type; };

template <struct Promote<unsigned long long,double{ typedef double

type; };

template <struct Promote<float,double{ typedef double type; };

template <struct Promote<long double,double{ typedef long double

type; };

template <struct Promote<char,long double{ typedef long double type; };

template <struct Promote<unsigned char,long double{ typedef long

double type; };

template <struct Promote<signed char,long double{ typedef long

double type; };

template <struct Promote<short,long double{ typedef long double type; };

template <struct Promote<unsigned short,long double{ typedef long

double type; };

template <struct Promote<int,long double{ typedef long double type; };

template <struct Promote<unsigned int,long double{ typedef long

double type; };

template <struct Promote<long,long double{ typedef long double type; };

template <struct Promote<unsigned long,long double{ typedef long

double type; };

template <struct Promote<long long,long double{ typedef long double

type; };

template <struct Promote<unsigned long long,long double{ typedef

long double type; };

template <struct Promote<float,long double{ typedef long double type; };

template <struct Promote<double,long double{ typedef long double

type; };