nikola said:
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.