Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to promote two template types for arithmitic operations like builtin types do?

If I have a generic struct/class:

template<typename T>
struct Container
{
    T value;
    Container(const Value& value) : value(value) { }
};

And I want to perform an operation on two of them:

template<typename T, typename U>
Container<T> operator+(const Container<T>& lhs, const Container<U>& rhs)
{
    return Container<T>(lhs.value + rhs.value);
}

The problem is that if lhs is of the type Container<int> and rhs is of the type Container<float>, then I'll get a Container<int> back. But if I were to do auto result = 2 + 2.0f, then result would of of type float. So the behavior is inconsistent between builtin types and custom types.

So how would I take the operator+ overload and make it return Container<float>, much like how C++ handles arithmetic promotion with builtin types?

like image 283
Therhang Avatar asked Oct 24 '15 21:10

Therhang


1 Answers

As far as you use one of the two types of the template, you risk to induce a cast on the result of the sum. As an example, if you accidentally choose int as your target type, even though the sum results in a float, it will be cast down to the chosen type.

Anyway, starting with C++11, you con rely on the decltype specifier as in the example above (or at least, you can do that if Container::T and Container::U are a types for which the + operator is defined).

I used also the auto specifier as return value for the operator+, for it is at our disposal starting from C++14 and it's really useful indeed.

It follows the working example above mentioned:

#include <iostream>
#include <vector>

template<typename T>
struct Container
{
    T value;
    Container(const T& value) : value(value) { }
};

template<typename T, typename U>
auto operator+(const Container<T>& lhs, const Container<U>& rhs)
{
    return Container<decltype(lhs.value+rhs.value)>{lhs.value + rhs.value};
}

int main()
{
    Container<int> c1{1};
    Container<float> c2{0.5};
    std::cout << (c1+c2).value << std::endl;
}
like image 157
skypjack Avatar answered Sep 27 '22 21:09

skypjack