Suppose I have a simple program to find the largest of two numbers of different datatypes and return the largest.I'm implementing it as a template to support generic datatypes

template<class T,class U>
T max(T t,U u)
return (t>u?t:u);

int main()
{
  int x=70;
  float y=100.5;
  max(x,y);
  return 0
}

Here the second generic datatype is the largest , but since return type is given as 1st type T(integer in this case ) the result gets truncated.Is there any other way to make the system identify and pass the return type also ? So that return type can also change dynamically depending on input. Please help me

Suppose I have a simple program to find the largest of two numbers of different datatypes and return the largest.I'm implementing it as a template to support generic datatypes

template<class T,class U>
T max(T t,U u)
return (t>u?t:u);

int main()
{
  int x=70;
  float y=100.5;
  max(x,y);
  return 0
}

Here the second generic datatype is the largest , but since return type is given as 1st type T(integer in this case ) the result gets truncated.Is there any other way to make the system identify and pass the return type also ? So that return type can also change dynamically depending on input. Please help me

It doesn't really make sense to compare two different types in general because two types might not be comparable to each other. Make it as suggested.

template<typename T>
T max(const T& lhs, const T& rhs){
   return lhs < rhs ? rhs : lhs;
}

And that, of course, is how std::max is coded.

Looking at the source code, its has a extra check to make sure its less than comparable and has multiple overloads

How its coded is obviously depend on the compiler. The version you posted is almost identical to the one that is included with VC++ 2010 Express. This is from <xutility>

//	ALGORITHM STUFF (from <algorithm>)
		// TEMPLATE FUNCTION max
template<class _Ty> inline
	const _Ty& (max)(const _Ty& _Left, const _Ty& _Right)
	{	// return larger of _Left and _Right
	return (_DEBUG_LT(_Left, _Right) ? _Right : _Left);
	}

Edited 5 Years Ago by Ancient Dragon: n/a

> Is there any other way to make the system identify and pass the return type also ?
> So that return type can also change dynamically depending on input.

Ask the compiler to deduce what the appropriate return type is:

template< typename A, typename B > inline
auto max_of( const A& a, const B& b ) -> decltype( a<b ? b : a )
{ return a<b ? b : a ; }

std::common_type<> in <type_traits> would do it for you:

template< typename A, typename B > inline
typename std::common_type<A,B>::type max_of( A a, B b )
{ return a>b ? a : b ; }

Which extends quite nicely to (if the implementation is conforming wrt variadic template parameters):

template< typename FIRST, typename... REST > inline
typename std::common_type<FIRST,REST...>::type max_of( FIRST first, REST... rest )
{ return max_of( first, max_of( rest... ) ) ; }

int main()
{
    std::cout << std::showpoint << max_of( 2UL, 56LL, 'a', 17.9f, 78, 89.4 ) << '\n' ;
}

Well, of course, AD and firstPerson's answers clearly doesn't do what you want.

vijayan121's answer is probably as much as you'll be able to do, that is, make the return type into whatever type that is common to both operand types. Which, again, isn't exactly what you want. And, in fact, it boils down to being equivalent to the std::max function because that too will deduce the single type "T" to be the common type that both operands can be promoted to. So, don't be fooled, vijayan121's solution is just a mirage (except for the slight benefit that only the result is converted to the destination type).

The fact is, you cannot make the result type depend on which value will be chosen at run-time. This is why C++ is called a "statically typed" language, types cannot change at run-time. So, there is no nice way to achieve what you want.

However, there is a reasonable way to do what you want, and it is using Boost.Variant, as so:

#include <utility>
#include <iostream>
#include <type_traits>
#include <typeinfo>

#include <boost/variant.hpp>

template <typename A, typename B> 
inline
boost::variant<A,B> max_of( const A& a, const B& b)
{ 
  std::cout << typeid(A).name() << " " << typeid(B).name() << std::endl;
  if(a < b)
    return b;
  else
    return a; 
};  //Notice here that I have not used the ( ? : ) operator because its return type
    // is fixed at compile-time, so, a regular if-statement has to be used.

int main() {
  double d = 42.0;
  int i = 69;
  auto p = max_of(d, i);
  std::cout << p.type().name() << std::endl;
  return 0;
};
This article has been dead for over six months. Start a new discussion instead.