954,487 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Have something to say? Contribute New Article Reply to this Article

generic programming return type problem

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

jeevsmyd
Junior Poster
142 posts since Oct 2008
Reputation Points: 8
Solved Threads: 0
 

why didn't you make both parameters the same type? T max(T t, T u)

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

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;
}
firstPerson
Senior Poster
3,923 posts since Dec 2008
Reputation Points: 841
Solved Threads: 608
 

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

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 
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

firstPerson
Senior Poster
3,923 posts since Dec 2008
Reputation Points: 841
Solved Threads: 608
 

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

Ancient Dragon
Retired & Loving It
Team Colleague
30,049 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,343
 

> 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 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' ;
}
vijayan121
Posting Virtuoso
1,606 posts since Dec 2006
Reputation Points: 1,159
Solved Threads: 287
 

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;
};
mike_2000_17
Posting Virtuoso
Moderator
2,134 posts since Jul 2010
Reputation Points: 1,634
Solved Threads: 457
 

This article has been dead for over three months

Post: Markdown Syntax: Formatting Help
You
View similar articles that have also been tagged: