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).
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.
Template parameters may have default arguments.
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.)
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.
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:
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).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>()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With