jeudi 31 décembre 2015

C++ 11 operator overload with return type deduction

I have a template class that depends on one type (for example template <typename T> class Vector). Now, I want to overload the arithmetic operators such that:

  • I can them to Vectors instantiated with two different types;
  • The result is deduced in the same way of the template instance types;

Example:

Vector<float> fv = {1.5, 2.5};
Vector<int> iv = {1,2};
auto s1 = fv + iv;   // s1 MUST be of type Vector<float> == {2.5, 4.5}
auto s2 = iv + fv;   // s2 MUST be of type Vector<float> == {2.5, 4.5}

I think that, in a generic purpose mathematical library that implements Matrices, Vectors, Polynomials, etc., this would be a feature that makes the difference in terms of usability.

I found three ways to obtain this result with C++11

  1. -> notation

    template <typename T, typename U>
    auto operator +(const Vector<T> &lhs, const Vector<U> &rhs)
        -> Vector<decltype(lhs[0]+rhs[0])>
    {
        Vector<decltype(lhs[0]+rhs[0])> res(lhs);
        res += rhs;
        return std::move(res);
    }
    
    
  2. declval

    template <typename T, typename U> 
    Vector<decltype(std::declval<T>()+std::declval<U>())> 
    operator +(const Vector<T> &lhs, const Vector<U> &rhs)
    {
        Vector<decltype(lhs[0]+rhs[0])> res(lhs);
        res += rhs;
        return std::move(res);
    }
    
    
  3. declval as default type arg

    template <typename T, typename U, 
              typename R = decltype(std::declval<T>()+std::declval<U>())> 
    Vector<R> operator *(const Vector<T> &lhs, const Vector<U> &rhs)
    {
        Vector<decltype(lhs[0]+rhs[0])> res(lhs);
        res += rhs;
        return std::move(res);
    }
    
    

What, in your opinion, the best approach to implement such a feature? If is there a FOURTH better solution I'll appreciate it.

Do you consider such "interworking" operators a worthwhile feature?

Thanks and Best Regards, Davide

Aucun commentaire:

Enregistrer un commentaire