5

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?

Therhang
  • 825
  • 1
  • 9
  • 15

1 Answers1

6

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;
}
skypjack
  • 49,335
  • 19
  • 95
  • 187
  • 1
    Looks good. You can make it more readable with a `make_container` helper function allowing the template argument to be deduced: `return make_container(lhs.value + rhs.value);` –  Oct 24 '15 at 21:19
  • Is there any additional runtime costs added by the operation performed in the `decltype`? Would it be better if I stored the result in a temporary `auto` variable and just do something like `return Container(result);`? – Therhang Oct 24 '15 at 21:27
  • The `decltype` is solved (thus wiped out) at compile time as well as the entire types system, so you won't have any additional runtime costs. – skypjack Oct 24 '15 at 21:30