Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing different types of parameters to a function template

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?

like image 213
Dumi B Avatar asked Dec 25 '16 10:12

Dumi B


People also ask

Which template can have multiple parameters?

C++ Templates: Templates with Multiple Parameters | C++ Tutorials for Beginners #65.

What is function template with multiple parameters in C++?

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.

Can we pass non-type parameters to templates?

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.

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.


2 Answers

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
like image 83
rgmt Avatar answered Sep 22 '22 23:09

rgmt


Use auto type deduction (since c++14):

template<typename t, typename u>
    auto add(t a, u b) {
        return a+b;
    }
like image 35
PiotrNycz Avatar answered Sep 21 '22 23:09

PiotrNycz