Consider this template:
template<typename t>
t add(t a, t b) {
return a+b;
}
How can I pass different types of parameters so the return value will be:
int
if both parameters are of type int
.
float
if one of the parameters is of type float
.
float
if both parameters are of type float
.
I've also tried having multiple parameters for the template:
template<typename t, typename c>
using them for the function parameters so they can be different (t add(t a, c b)
) but what I can't wrap my head around is how can I change the type of function (int, float, double, etc.) depending on the return type?
C++ Templates: Templates with Multiple Parameters | C++ Tutorials for Beginners #65.
Multiple parameters can be used in both class and function template. Template functions can also be overloaded. We can also use nontype arguments such as built-in or derived data types as template arguments.
However, template type parameters are not the only type of template parameters available. Template classes and functions can make use of another kind of template parameter known as a non-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.
What you want is std::common_type
:
template<typename T0, typename T1>
typename std::common_type<T0, T1>::type add(T0 a, T1 b) {
return a+b;
}
The documentation states:
For arithmetic types, the common type may be viewed as the type of the (possibly mixed-mode) arithmetic expression such as T0() + T1() + ... + Tn().
But, as pointed by @Jarod42 in the comments, this is just a view, and may be wrong in some cases: for example, std::common_type<char, char>::type
is char
whereas the arithmetic expression char() + char()
yields int
.
A more complete implementation may explicitly cast the result to remove possible warnings in the cases cited above:
template<typename T0, typename T1, typename R = std::common_type_t<T0, T1>>
R add(T0 a, T1 b) {
return static_cast<R>(a+b);
}
Here std::common_type
is used by default for return type, but since it is a template parameter, you may specify a different type when using the function (may be useful in more complex use cases):
char a = 1, b = 2;
add<decltype(a), decltype(b), int>(a, b);
Using std::conditional
and std::is_same
, an even more complete solution proposed by @Jarod42 in the comments allows to have template R
as first parameter, and keep automatic deduction for a
and b
:
template <typename R, typename T0, typename T1>
using ResType = std::conditional_t<
std::is_same<void, R>::value,
std::common_type_t<T0, T1>, // default
R // R was explicitly specified: use it
>;
template <typename R = void, typename T0, typename T1>
ResType<R, T0, T1> add(T0 a, T1 b)
{
return static_cast<ResType<R, T0, T1>>(a + b);
}
Usage:
char a = 1, b = 2;
add(a, b); // returns char
add<int>(a, b); // returns int
Use auto type deduction (since c++14):
template<typename t, typename u>
auto add(t a, u b) {
return a+b;
}
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