0

I am writing a class that has a std::vector as member, and I'd like to be able to modify its data in bulk by using default operators +/+=, */*=, etc taking a scalar as argument, e.g.

MyClass<float> obj;
obj += 4.0;

I'm tring to define the operator overload as:

template <class _type> 
matrix2D<_type>& matrix2D<_type>::operator=(matrix2D<_type> _mat){
    std::swap(_mat,*this);
    return *this;
};

template <class _type>
template <typename _input_type>
myClass<_type> myClass<_type>::operator*(_input_type _val) { 
    for (int i = 0; i < data.size(); ++i) data[i] *= _val; 
    return *this;
};

template <class _type>
template <typename _input_type>
myClass<_type> myClass<_type>::operator*=(_input_type _val) { 
    for (int i = 0; i < data.size(); ++i) data[i] *= _val; 
    return *this;
};

I get no compile or runtime errors, but the values remain unchanged. I've tried to a multitude of different types of return values (MyClass&, void) and passing a myClass object as argument. What am I missing?

joaocandre
  • 1,621
  • 4
  • 25
  • 42
  • What you seem to want already exists as [`std::valarray`](https://en.cppreference.com/w/cpp/numeric/valarray). – Some programmer dude Jun 28 '18 at 16:13
  • As for a possible reasons for your problem, assignment operators are supposed to return `*this` *by reference*. And your `operator*` is wrong as well, it should not modify `this` or its members. I suggest you read e.g. [this operator overloading reference](http://en.cppreference.com/w/cpp/language/operators), especially look closer at [the canonical implementations](http://en.cppreference.com/w/cpp/language/operators#Canonical_implementations). And of course [read a few good books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282). – Some programmer dude Jun 28 '18 at 16:14
  • From what I saw, your instance is modified (even for `operator*` :-/ ). – Jarod42 Jun 28 '18 at 16:18
  • I was following the guidelines in [here](http://courses.cms.caltech.edu/cs11/material/cpp/donnie/cpp-ops.html). I've tried return the class object by reference - the result is the same. I don't understand exactly why I should not modify `this`? – joaocandre Jun 28 '18 at 16:54
  • If you have `a = b * c`, should either `b` or `c` be modified? No, that's not how multiplication (other other arithmetic operations) work. – Some programmer dude Jun 28 '18 at 17:10
  • @Someprogrammerdude fair enough, that should be the case for the `*` operator. But what about the compound `*=`? – joaocandre Jun 28 '18 at 22:25
  • No that would of course need to modify the recipient. `a *= b` would indeed modify `a`. – Some programmer dude Jun 28 '18 at 22:28

1 Answers1

0

Don't write this naive;y, or it's going to be the slowest implementation the world has seen. And definitely don't use std::val_array, as it is not optimised with any compiler I know of. It was dead in the water with it's comception There is a Matrix class in my PhD work, if you care get inspired there: https://github.com/kvahed/codeare/blob/master/src/matrix/Matrix.hpp

As a rule of thumb stick to std::vector and use the functionality in <algorithm> like std::accumulate, std::transform, .... And always implement the assignment version of the operator and use that every where else.

So for example to cover both scalar and matrix elementwise multiplication:

template <typename T>
class Matrix {
  public:
  ...
  Matrix<T>& operator*=(const T& t) {
    if (t != T(1)) {
      std::transform(
        v_.begin(), v_.end(), v_.begin(), std::bind2nd(std::multiplies<T>(), t));
    }
    return *this;
  }
  Matrix<T>& operator*=(const Matrix<T>& m) {
    std::transform(
      v_.begin(), v_.end(), m.begin(), v_.begin(), std::multiplies<T>()));
    return *this;
  }
  template<typename S>
  Matrix<T> operator* (const S& s) {
    return *this *= s;
  }
  ...
  private:
    std::vector<T> v_;
}

But this is neglecting SIMD instruction sets your CPU will be capable of: https://github.com/kvahed/codeare/blob/master/src/matrix/SIMDTraits.hpp

But there are some stuff that you should keep in mind that turn out to be non-trivial. Particularly, when your matrices are not allocated on the heap, memory can be unaligned. This will kill you entirely. Calculating by hand is faster then. https://github.com/kvahed/codeare/blob/master/src/matrix/Allocator.hpp

Seriously, getting what you want to build right is a lot of work and test code.

TLDR: If you are looking for naive implementation use <algorithm> stay clear of val_array. Feel free to use my stuff. If you got questions, anytime.

Kaveh Vahedipour
  • 3,412
  • 1
  • 14
  • 22