nikola wrote:

Hi all,

I was working with a simple function template to find the min of two values.

But since I would like the two values to be different (type) I dont know

what kind of value (type) it will return. I tried to write something like

this:

template <class Type1, class Type2, class Type3>

Type3 findMin(Type1 x, Type2 y){

return (x < y) ? x : y;

}

but it says it cannot deduce template argument for 'Type3'

Can anyone help? Thanx

This is a classic template issue.

What you really want is :

template <typename T1, typename T2>

typename Promote<T1,T2>::type min( const T1 & x, const T2 & y )

{

return x < y ? x : y;

}

Where Promote is a template that will perform the right "promotion" for

T1 and T2.

If the "typeof()" function was standard, you could simply do this:

template <typename T1, typename T2>

struct Promote

{

typedef typeof( T1() + T2() ) type;

};

.... but alas, things are not so simple in the standard world.

We need to figure it out ourselves so we have to use partial template

specialization.

Start with the basic template:

template <typename T1, typename T2>

struct Promote

{

};

// the same types are the same ! cool

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; };

//

// and now the min template ...

template <typename T1, typename T2>

typename Promote<T1,T2>::type min( const T1 & x, const T2 & y )

{

return x < y ? x : y;

}

That's a bit long winded. However, some people might arge that type

promotion is a bad thing and that the developer really needs to make

sure that the parameters to min (or max) are the same type, in which

case the template becomes easy to write.