In C++ How do I template the return value to be unique from the parameter value?

18,359

Solution 1

The most generic method is to have a helper template

template <typename T>
struct calc_return {
  using type = T;
};

template <class T>
typename calc_return<T>::type divide(T number)
{
   return number/10;
}

Now if there are exceptions to the rule, you specialize calc_return using whatever logic you'd like:

// Prior to the declaration of divide()
template <>
struct calc_return<int> {
  using type = double;
};

Solution 2

In this case I think you want

template <class T>
auto divide(T number) -> decltype(number/10.0)
{
   return number/10.0;
}

The compiler has a decent idea what the return type should be, if you at least divide by 10.0 instead of 10.

Or C++14 style:

template <class T>
auto divide(T number) // Compiler will figure it out from the return statement.
{
   return number/10.0;
}

Solution 3

Do you mean something like this:

template <class T, class T1>
T1 divide(T number)
{
    return ((T1)number) / 10;
}

....

double res = divide<int, double>(2);
Share:
18,359
YelizavetaYR
Author by

YelizavetaYR

Updated on June 04, 2022

Comments

  • YelizavetaYR
    YelizavetaYR almost 2 years

    In C++ How do I template the return value to be unique from the parameter value? My code looks as follows - now if data type of number is int going in I want it as a double going out.

    template <class T>
    T divide(T number)
     {
        return number/10;
     }
    

    in main I have this

     divide(5);
     divide(2.5);
    

    In the case of 2.5 the value going in and out will be type double so there isn't a problem but in the case of 5 it goes in as an int but I need it to not be truncated and returned as type double.

    template <class T, Class T1>
    T1 divide(T number)
     {
        return number/10;
     }
    

    That doesn't work because its looking for two parameters in the functions.

    T1 template <class T>
    T1 divide(T number)
     {
        return number/10;
     }
    

    this gives me no declaration of storage class or type specifier - when I add the word class to that line before T1 I get the error message: function returns incomplete type.

    • Jerry Coffin
      Jerry Coffin over 9 years
      Is the return always double, or does it still depend on the input (e.g., for char or short you want return to be a float, and for int or long you want it to return double?
    • YelizavetaYR
      YelizavetaYR over 9 years
      It's not always a double, that's why I'd like to template it. I want to return the best possible fit for the specified data type.
    • Jerry Coffin
      Jerry Coffin over 9 years
      So you need to decide (and tell us) exactly what is the best fit for any given input type. To help you much, we need to know what result you want and how a result is determined based on an input.
    • YelizavetaYR
      YelizavetaYR over 9 years
      @JerryCoffin thats where my question stands - the input type can be any numerical value (maybe even a char). But the output type, the return type is different in some instances. specially in the int vs. double or int vs float etc. The idea of the template is that any numerical value can go in but a different one can be returned.
    • Jerry Coffin
      Jerry Coffin over 9 years
      With templates you can build a mapping from input type(s) to output type(s). But, like any programming, you have to decide on what that mapping should be. The compiler can do what you tell it, but you still need to tell it what you want (and right now, it sounds to me like you don't really even know what you want).
  • YelizavetaYR
    YelizavetaYR over 9 years
    This doesn't work for me, the compiler is looking for a function header with two variables. It should have one and return one (but the return is possibly different)
  • YelizavetaYR
    YelizavetaYR over 9 years
    I'll be honest I'm not 100% sure, I understand what's being done here.
  • MSalters
    MSalters over 9 years
    The idea is that calc_return<double>::type is just double, etc - but you can specialize calc_return<int>::type to be whatever you want.
  • AlexD
    AlexD over 9 years
    @YelizavetaYR What do you mean saying that it does not work? divide<int, double>(....) instantiates/calls the function with parameter of type int and the result of type double.
  • YelizavetaYR
    YelizavetaYR over 9 years
    When i tried running this code - The call to the function would look like divide(x); and the compiler would throw an error telling me that my parameters don't match - I am only passing one but asking for two to be returned. The issue is we only want to pass one parameter and have one return value of a different type. Sorry if my question was unclear i didn't mean to cause confusion.
  • YelizavetaYR
    YelizavetaYR over 9 years
    decltype is specifying to return a type? Is it a pointer? I'm not sure how this works. IS this basically saying auto will be whatever the pointer returns? does that mean the contents of the function would have to follow the decltype in the parenthesis?
  • MSalters
    MSalters over 9 years
    The auto ... -> part means that I'll declare the return type later (I do so because it depends on number). decltype is "declared type", the type of the expression number/10.0. Obviously that depends on T number. In particular, it means there's no implicit conversion in the return statement, as the return type exactly matches the return expression. If your compiler is brand new (C++14 standard), you actually don't need the -> decltype() part.
  • AlexD
    AlexD over 9 years
    @YelizavetaYR Yes, if you call divide(x), the compiler cannot instantiate the function. But if you call divide<double,int>(x), the compiler should be happy.
  • Oleksa
    Oleksa over 3 years
    Why do you want to do this and not just template <class T, class RetT> and specify the return type through the template parameter list?
  • MSalters
    MSalters over 3 years
    @OleksijPlotnyc'kyj : because the intent is to specify the return type as the author of the template, not the user. (Think libraries)