user1082764
user1082764

Reputation: 2015

How can I convert between types in a template and back to the original type

I am wanting to make a template function that adds three numbers. The type may be int or char or string. How can I add these then return the correct value using the same type. Example: three strings of numbers {5,6,7} should add up to 18 then return 18 as a string. three chars of numbers {5,6,7} should add up to 18 then return 18 as a char.

template <class MyType>
MyType GetSum (MyType a, MyType b, MyType c) {
  return (a+b+c);
}

  int a = 5, b = 6, c = 7, d; 
  char e = '5', f = '6', g = '7', h; 
  string i= "5", j= "6", k= "7", l; 

  d=GetSum<int>(a,b,c);
  cout << d << endl;

  h=GetSum<char>(e,f,g);
  cout << h << endl;

  l=GetSum<string>(i,j,k);
  cout << l << endl;

This code works for int but obviously not for char or string. I am not sure how to convert from an unknown type to int and back so i can add the numbers.

Upvotes: 0

Views: 2499

Answers (3)

jxh
jxh

Reputation: 70382

You can implement explicit conversion template functions, where each is implemented with template specialization. For instance:

template <typename MyType> int ToInt (MyType);
template <> int ToInt<int> (int x) { return x; }
template <> int ToInt<std::string> (std::string x) { return std::stoi(x); }
template <> int ToInt<char> (char x) { return std::stoi(std::string(&x, 1)); }

template <typename MyType> MyType FromInt (int);
template <> int FromInt<int> (int x) { return x; }
template <> std::string FromInt<std::string> (int x) {
    std::ostringstream oss;
    oss << x;
    return oss.str();
}
template <> char FromInt<char> (int x) {
    static const std::string map("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
    return map.at(x);
}

Then, the GetSum() would call ToInt<>() on the arguments, compute the sum, and then call FromInt<>() to convert the value back to the original type:

template <typename MyType>
MyType GetSum (MyType a, MyType b, MyType c) {
    int aa = ToInt(a);
    int bb = ToInt(b);
    int cc = ToInt(c);
    return FromInt<MyType>(aa + bb + cc);
}

As can be seen in this demo, for your same program, the output is:

18
I
18

The reason for I for the char case is that the conversion assumes the resulting value can be expressed as a single base 36 digit.

Upvotes: 0

stefan
stefan

Reputation: 10345

You want addition as if the items would be integers though may be int, char or std::string.

That means, first get them to be integers, then convert back to the original type:

template <typename T>
T sum(T t1, T t2, T t3)
{
   std::stringstream input;
   input << t1 << " " << t2 << " " << t3;
   int sum = 0;
   int item;
   while ( input >> item )
   {
      sum += item;
   }
   // at this point we have the wanted value as int, get it back in a general way:
   std::stringstream output;
   output << sum;
   T value;
   output >> value;
   return value;
}

I'd be a bit careful with the addition of chars in that way. '18' isn't exactly meaningful afaik, or probably at least platform dependent.

You'll need to include <sstream> in your project to use std::stringstream.

Upvotes: 2

anatolyg
anatolyg

Reputation: 28241

You can use boost::lexical_cast to convert between integer and string types.

template <class MyType>
MyType GetSum (MyType a, MyType b, MyType c)
{
    int int_a = boost::lexical_cast<int>(a);
    int int_b = boost::lexical_cast<int>(b);
    int int_c = boost::lexical_cast<int>(c);
    int sum = int_a+int_b+int_c;
    return boost::lexical_cast<MyType>(sum);
}

If you are not allowed, or don't want, to use boost, just implement the function template lexical_cast yourself (you will have to implement several template specializations, but each individual one is easy).

Upvotes: 0

Related Questions