9

I'm implementing some classes for linear algebra operations on very small constant size vector and matrices. Currenty, when I do :

MyMathVector<int, 3> a ={1, 2, 3};
MyMathVector<double, 3> b ={1.3, 2.3, 3.3};
std::cout<<"First = "<<a+b<<std::endl;
std::cout<<"Second = "<<b+a<<std::endl;

Then First = {2, 4, 6} and Second = {2.3, 4.3, 6.3}, because the second element is casted to the first element type by the compiler. Is there any "easy" way to provide the same kind of automatic casting like in native C++ : int+double=double, double+int=double ?

Thank you very much.

EDIT : With the syntax given from answers, I got the operator+ working. But I tried the following syntax, and the compilation fails with the error : expected a type, got ‘std::common_type<T, TRHS>::type’

#include <iostream>
#include <type_traits>

template<class T> class MyClass
{ 
    public:
        MyClass(const T& n) : _n(n) {;}
        template<class TRHS> MyClass<typename std::common_type<T, TRHS>::type> myFunction(const MyClass<TRHS>& rhs) 
        {
            return MyClass<std::common_type<T, TRHS>::type>(_n*2+rhs._n);
        }
        T _n; 
};

int main()
{
    MyClass<double> a(3);
    MyClass<int> b(5);
    std::cout<<(a.myFunction(b))._n<<std::endl;
}

What is the problem of that syntax ?

Vincent
  • 57,703
  • 61
  • 205
  • 388

3 Answers3

9

Use std::common_type:

template <std::size_t s, typename L, typename R>
MyMathVector<typename std::common_type<L, R>::type, s> operator+(MyMathVector<L, s> const& l, MyMathVector<R, s> const& r)
{
    // do addition
}

Ot in case of the member function (in the class body, where T and s are visible):

template <typename TRHS>
MyMathVector<typename std::common_type<T, TRHS>::type, s> operator+(MyMathVector<TRHS, s> const& rhs) const
{
    // do addition
}
yuri kilochek
  • 12,709
  • 2
  • 32
  • 59
  • Great ! For the + operator this syntax works well but it crashes for others functions that needs to be a class member. What is the syntax for a class member function where T is the class type, and TRHS is the type of the passed parameter ? – Vincent Jul 31 '12 at 16:23
  • @Vincent edited answer accordingly, apparently you cannot put code blocks in comments. – yuri kilochek Jul 31 '12 at 16:31
  • Thank you very much. I edited the original question because I don't see the syntax error in the provided piece of code... – Vincent Jul 31 '12 at 16:42
  • Add `typename` before `std::common_type::type` in `operator+` body as in return type. See [here](http://stackoverflow.com/questions/1123080/why-do-we-need-typename-here) from more info. – yuri kilochek Jul 31 '12 at 16:50
5

Use the std::common_type trait to figure out the correct result type for a mixed operation.

The linked page even has an example that's very similar to your case.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
4

Absolutely; use decltype:

template<typename Other>
auto operator+(const MyMathVector<Other, size> &other)
    -> MyMathVector<decltype(std::declval<T>() + std::declval<Other>()), size>;

As a non-member operator, it might be better to say what you mean by actually referencing a vector member:

template<typename size, typename L, typename R>
auto operator+(const MyMathVector<L, size> &l, const MyMathVector<R, size> &r)
    -> MyMathVector<decltype(l[0] + r[0]), size>;
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • This requires `T` and `Other` to be publically default-constructible. Better to say `std::declval()` etc. – Kerrek SB Jul 31 '12 at 15:58