Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template parameter as return type

I stumbled upon this some time ago and I finally need to get an answer to this!

The problem is as follows:

#include <iostream>

using namespace std;

template <class FIRST, class SECOND>

FIRST multiply(FIRST a, SECOND b){
    return a * b;
}

int main(){
    int x = 39;
    double y = 38.38;
    cout << multiply(x, y) << endl;
}

In this C++ code I have two template parameters and the return type of the function is the type of one parameter. My problem with that is that the return type has to be (in this case) the same type like the variable a is. I tried it with a THIRD template parameter but it gave me an compiling error, could anyone please explain this to me?

I don't want to make it generally a long or something, I want the return type to be the 'biggest' type of the variables passed, so that it will work with chars and strings as well (for those I would obviously do another operation or something, this is only an example).

like image 733
fkarg Avatar asked Nov 05 '14 15:11

fkarg


People also ask

What is template type parameter?

A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

Can template parameters have default values?

Template parameters may have default arguments.

Can a template be a template parameter?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)

Can we use non-type parameters as argument templates?

A non-type template argument provided within a template argument list is an expression whose value can be determined at compile time. Such arguments must be constant expressions, addresses of functions or objects with external linkage, or addresses of static class members.


1 Answers

The canonical approach to deal with situations like this is to return the appropriate type returned from the result of the operation called:

template <typename FIRST, typename SECOND>
auto multiply(FIRST a, SECOND b) -> decltype(a * b) {
    return a * b;
}

This use-case is pretty much the motivating example for adding late return types: the result type of an operation can be entirely non-predictable. This leads to two needs:

  1. It needs to be possible to determine the type of an expression which is what decltype(expr) does: it yields the type of what expr is declared to be: when expr is a function call you'd look at the function declaration and that's what decltype(expr) yields (well, there are some complexities in there).
  2. To actually formulate expr it is frequently necessary to get hold of function arguments. Thus, a new approach to declare function was introduced:

    auto function-name(args) -> return-type

    The auto keyword is merely indicating that the function will use a late return type. The function-name and args are used the same as in other functino declaration. The return-type then follows at a point where parameter names can be used, i.e., after the -> is the return->type which is is normally in front of the function declaration.

    Put differently, if return-type does not refer to the names of arguments, the declaration above is equivalent to this declaration:

    return-type function-name(args)

    If return-type refers to a name introduced in args you'd need to deal with getting object of the appropriate types, e.g., using std::declval<T>().

like image 102
Dietmar Kühl Avatar answered Sep 30 '22 14:09

Dietmar Kühl