c++classoperators

Define custom class operator in c++


I have this class which aims to mimic the behavior of a vector in MATLAB, I’m building this just as a college exercise.

#include <iostream>
#include <vector>
#include <tuple>
using namespace std;

double const pi = 3.141592;

class mv{
    public:
        mv(size_t size = 0, double init = 0) {for(size_t i = 0; i < size; i++) a.push_back(init);};

        size_t size() const {return a.vector<double>::size();};
        void print() const {for(auto &el : a) std::cout << el << " ";}; 
        double get(size_t n) const {return a[n];};

        double& operator[](size_t n) {return a[n];};

    private:
        vector<double> a;
};

I want to add the multiplication by a scalar and I want it to work in both ways, i.e. both a * 3 and 3 * a should work as shown below.

int main() {
    mv a(5, 1);
    a[3] = 2;
    
    mv b(5);
    b = a * pi;
    b.print(); 
    cout << endl;

    mv c(5);
    c = pi * a;
    c.print(); 
    cout << endl;

    return 0;
}

The most obvious way to do this is

mv operator*(const mv& a, const double& scalar){
    mv res(a.size());
    for(size_t i=0; i<a.size(); i++) res[i] = a.get(i) * scalar;
    return res;
};

mv operator*(const double& scalar, const mv& a){
    mv res(a.size());
    for(size_t i=0; i<a.size(); i++) res[i] = a.get(i) * scalar;
    return res;
};

But I would really like to do it with just one function, so I’ve explored this option

template<typename T, typename V>
mv operator*(const T& lhs, const V& rhs){
    auto tuple = std::tie(lhs, rhs);
    return mvTimes(std::get<const mv&>(tuple), std::get<const double&>(tuple)); 
};

mv mvTimes(const mv& a, const double& scalar){
    mv res(a.size());
    for(size_t i=0; i<a.size(); i++) res[i] = a.get(i) * scalar;
    return res;
};

This works but feels clumsy and prone to errors (for example I should then have to catch exceptions thrown by std::get). What is the best way to do this?


Solution

  • You can define one operator in terms of the other:

    mv operator*(const double& scalar, const mv& a){
        mv res(a.size());
        for(size_t i=0; i<a.size(); i++) res[i] = a.get(i) * scalar;
        return res;
    };
    
    mv operator*(const mv& a, const double& scalar){
        return scalar * a;
    };