1

I am trying to add 2 vectors using overloaded + operator. https://stackoverflow.com/a/4421719/9329547 answer shows

inline X operator+(X lhs, const X& rhs)
{
  lhs += rhs;
  return lhs;
}

My case is I want to pass 2 vectors to class, then a function will modify them and will add using another method and return it. Here is the code.

class VO
{
private:

const std::vector<double> &vec1;
const std::vector<double> &vec2;

public:
VO (const std::vector<double> &x, const std::vector<double> &y): vec1(x), vec2(y) {}

std::vector<double> operator + (const std::vector<double> &, const std::vector<double> &) {}

std::vector<double> foo(....) 
{ 
//vectors vec1, vec 2 are modified here then want to add them
std::vector<double> v3 = vec1 + vec2;
return v3;
}
};

int main()
{
std::vector<double> a={1,2,3,4,5}, b={9,8,7,6,5},c;
VO obj(a,b);
c=obj.foo();
return 0;
}

In this case, I am not sure how can I use this to add 2 vectors.

Edit:

I can create vectorAdd method in the class, pass 2 vectors and get addition. But I want to use operator + for that. Operator + is overloaded in many scientific libraries to add vectors (arrays).

Edit 2:

If I use my original code, I get error error C2804 binary operator + has too many parameters. I am trying to add 2 vectors such that if a={1,2,3,4,5}, b={9,8,7,6,5}, then a+b = {1+9, 2+8, 3+7, 4+6, 5+5} = {10,10,10,10,10}

bn4365
  • 31
  • 1
  • 6
  • 1
    @Borgleader That looks like merging two arrays. My question is different one. – bn4365 Feb 09 '18 at 13:53
  • it should be a free function. The operator you wrote would be called like that `obj.operator+(a,b);` and you cannot do `a+b`. – 463035818_is_not_an_ai Feb 09 '18 at 13:55
  • this maybe makes a better dupe: https://stackoverflow.com/questions/4421706/what-are-the-basic-rules-and-idioms-for-operator-overloading – 463035818_is_not_an_ai Feb 09 '18 at 13:56
  • @user463035818, please see my (updated) question. I already linked that question. – bn4365 Feb 09 '18 at 14:00
  • 1
    oh, didnt see that. The problem is that you do something different in your code than what that answer suggests. You implemented `operator+` as member function of `OV`, but `operator+` for vectors can only be a free function.. that being said, it is the correct dupe – 463035818_is_not_an_ai Feb 09 '18 at 14:06
  • its a bit hard to find, but if you search for "According to our rules of thumb, + and its companions should be non-members, while their ..." you will find the relevant paragraph – 463035818_is_not_an_ai Feb 09 '18 at 14:09
  • 1
    btw I voted to reopen because the currently assigned dupe really is about something different – 463035818_is_not_an_ai Feb 09 '18 at 14:14
  • this->operator+(a, b). thise library you talk about do not use std::vector as their operating class, because they need operator+ as a free function for mathematical vector type. std::vector is a dynamic array type , inept for this use unless you make a class-wrapper – Swift - Friday Pie Feb 09 '18 at 16:04
  • 2
    Which `+` do you mean -- appending or element-wise? That is why there is no default `operator+` on `vector`. Second, you want a `+` that only works within a method of the class? No can do; `+` within a method of the class doesn't look for member `+`, it looks at the `+` on the two types being added. You need to clarify what you want so an appoach can be found that solves your problem; I can think of a dozen solutions to a dozen different problems, but I cannot determine which of those dozen problems are actually a way to solve your problem (if any). – Yakk - Adam Nevraumont Feb 09 '18 at 16:44
  • Why is it important that the vectors are added _using another method_? Why would you want a method called `operator+` when the only reason for using that name is the syntactic sugar you specifically _don't_ get in this case? – Useless Feb 09 '18 at 17:54
  • @Useless there is vector addition, then subtraction, then multiplication and so on. Imagine you want to do `x=a*y+z`, `x,y,z` are `std::vectors` and `a` is `int`. "syntactic sugar" is much needed. – bn4365 Feb 09 '18 at 18:58
  • Yes, I understand the value of syntactic sugar. I don't understand why you insist on putting `operator+` in a class unrelated to the things you want to add. I don't understand what `V0` is supposed to be _for_, or how you expect the compiler to guess where you want it to get `operator+` _from_. Are you just using it as a namespace? – Useless Feb 09 '18 at 19:04
  • @Useless I was confused, I will put `operator+` in another class. Purpose of class `VO` is to modify the input vectors. What I don't understand is why I cannot take 2 arguments to `operator+`. I mentioned that in Edit 2. – bn4365 Feb 09 '18 at 19:08
  • Wait, why are you putting the operator in a class **at all**? Not _why are you putting it in `V0` instead of `W1`_ or whatever. What do you think classes are _for_? They're not just random assortments of functions. If you want `vector operator+(vector,vector)` to work, you can't alter `std::vector`, so it must be a free function. Not in any class. – Useless Feb 09 '18 at 19:17
  • @Useless I was thinking to put together similar functions on vectors such as `+,-,*`, that's why I thought I should create a class and have all these together. But from your comment it looks like it doesn't work that way. By the way, can you explain more on: `if you want vector operator+(vector,vector) to work, you can't alter std::vector`. How someone can alter `std::vector` if put in a class and if put as a "free" function? – bn4365 Feb 09 '18 at 19:36

3 Answers3

3

It's not entirely clear what you're trying to achieve, but you seem pretty confused about how and why to use operator overloading.

I am trying to add 2 vectors using overloaded + operator

OK, the purpose of this overloaded operator is that you can type

vector<double> a, b, c;
// ... populate a and b ...
c = a + b;

as if vector<double> were a primitive type like int or a simple double.

The whole point is to get the same syntax for built-in and user-defined types, so that later we can write generic code that works identically for both. For example, std::plus and std::accumulate work for any type with operator+ defined, whether you're adding integers or vectors or something else.

For this to work (and operator overloading to be worthwhile), your custom operator+ must be found by the usual name lookup rules when you write a + b.

Then you say

I want to pass 2 vectors to class, then a function will modify them and will add using another method

but using a class method instead of a free function doesn't satisfy the requirements above. V0::operator+ won't be found when you type a + b. (In fact V0::operator+ can anyway only be a method for adding something to a V0, because it must be non-static if it is a method, and so the left-hand-side will always be a V0 object).

If you still want addition to be a method of V0, there's no reason to call it operator+, because the syntax won't be the same anyway.

Conversely if you do want the same syntax, it should be a free function in order for the name lookup to work.

You say you want to overload the operator because it is overloaded in many scientific libraries, but that doesn't explain wanting it to be a method of a class other than the type you're adding

  • if you want to use one of those libraries and provide it an operator+ to use, then putting the operator inside an unrelated class won't achieve anything. How will the library know it's supposed to call V0::operator+ when adding two vector<double>? That's not the way anything works
  • if you want to imitate the style of those libraries, the only operator+ associated with your V0 type would be used to add V0 instances. And it should still be a free function.
Useless
  • 64,155
  • 6
  • 88
  • 132
1

Here is a possible implementation of vector addition, using the guidelines you linked:

#include <iostream>
#include <vector>
#include <exception>

template<typename T>
std::vector<T>& operator+=(std::vector<T> &lhs, const std::vector<T> &rhs) {
    typedef std::vector<T>::size_type size_type;
    if (lhs.size() != rhs.size())
        throw std::length_error("vectors must be same size to add");

    for (size_type i = 0; i < lhs.size(); ++i)
        lhs[i] += rhs[i];
    return lhs;
}

template<typename T>
std::vector<T> operator+ (std::vector<T> lhs, const std::vector<T> &rhs) {
    typedef std::vector<T>::size_type size_type;
    if (lhs.size() != rhs.size())
        throw std::length_error("vectors must be same size to add");
    return lhs += rhs;
}

int main()
{
    std::vector<double> a = { 1,2,3,4,5 }, b = { 9,8,7,6,5 }, c;
    c = a + b;
    for (auto x : c)
        std::cout << x << ' ';
    return 0;
}

Output:

10 10 10 10 10

You could define a math vector class which has-a std::vector (because no virtual destructor), and define the math operators on that, so that you can't accidentally call this operator on std::vectors which are not intended to be math vectors. Personally, I would just get one of those math libraries you mentioned, and use it. No need to reinvent the wheel.

Kenny Ostrom
  • 5,639
  • 2
  • 21
  • 30
  • Your `operator +` can be simplified: typedef unused, and check already done in `+=`. – Jarod42 Feb 09 '18 at 18:14
  • So, the same class cannot have `foo()` and `operator +`, referring to my question. – bn4365 Feb 09 '18 at 19:00
  • Well, you could, but ... VO::foo and VO::operator+ seem completely unrelated, because foo does other stuff, and I don't even know how to add two different instances of VO. – Kenny Ostrom Feb 10 '18 at 14:15
1

A vector is a fixed type. You should not add + to it.

You can extend vector like this:

template<class T>
struct my_vector:std::vector<T> {
  using std::vector<T>::vector; // get vector's constructors

  my_vector& operator+=( my_vector const& rhs )& {
    if (size() < rhs.size()) resize(rhs.size());
    for (std::size_t i = 0; i < rhs.size(); ++i)
      (*this)[i] += rhs[i];
    return *this;
  }
  friend my_vector operator+( my_vector lhs, my_vector const& rhs ) {
    lhs += rhs;
    return lhs;
  }
  my_vector& operator*=( my_vector const& rhs )& {
    if (size() < rhs.size()) resize(rhs.size());
    for (std::size_t i = 0; i < rhs.size(); ++i)
      (*this)[i] *= rhs[i];
    return *this;
  }
  friend my_vector operator*( my_vector lhs, my_vector const& rhs ) {
    lhs *= rhs;
    return lhs;
  }
};

Now, use my_vector<double> instead of std::vector<double>.

Now, you could add this operator+ in the namespace where you are doing the work, but that generally isn't a good idea. Operations on types should be part of the type or in the type's namespace to avoid surprises.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524