Thread: overloading operators for vector addition

  1. #1
    Registered User
    Join Date
    Oct 2005
    Posts
    271

    overloading operators for vector addition

    Hello everyone,

    I'm trying to overload some operators for the vector class but my attempts don't seem to do anything. They compile fine, they just won't add/subtract/multiply...

    Here's a sample for the + operator.

    Code:
    template <class T1, class T2>
    vector<T1> &operator+(vector<T1>& v1, vector<T2>& v2)
    {
      for(UINT i = 0; i < v1.size(); i++)
            v1[i] += v2[i];
      return v1;
    }
    The when I call it, it's like this
    Code:
    vector<int> v1, v2;
    v1.assign(4, 4);
    v2.assign(4, 6);
    
    v1 = v1 + v2;
    Then when I look in v1, the values are still {4, 4, 4, 4}.

    So, how do you do it?

  2. #2
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Well, first those parameters should be const references. They aren't going to be changed. You also avoid a copy and this can be extremely important if those vectors are BIG.

    Second... your code is right. So... what exactly is happening?

    EDIT: are you by any chance looking at v1 with the debugger and a breakpoint set on top of the v1 = v1 + v2; line? You should step once so that the line actually is evaluated.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  3. #3
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    Well, I didn't post my actual code. It's
    Code:
    template <class T1, class T2>
    vector<T1> &operator+(vector<T1>& v1, vector<T2>& v2)
    {
      for(UINT i = 0; i < v1.size(); i++)
        {
          if(!v2.at(i))
            v1[i] += v2[i];
          else
            break;
        }
      return v1;
    }
    I did this so I could add vectors of different length. I wonder if that could have been the problem. And tried adding the const keyword to the two parameters (you are talking about something like this:
    Code:
    vector<T1> &operator+(const vector<T1>& v1, const vector<T2>& v2)
    right?)

    Well, adding the const gave a compile error.
    Code:
    perceptron.cpp:37: error: assignment of read-only location
    perceptron.cpp:41: error: invalid initialization of reference of type '
       std::vector<float, std::allocator<float> >&' from expression of type 'const
       std::vector<float, std::allocator<float> >'
    Anyway, you add two vectors and the value in the first vector does not change.

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    Creating operators on standard library containers isn't really a good idea except perhaps for learning purposes.

    However, for this you can make a copy of v1 and then add v2's elements to the copy's elements. The easiest way to do this is to make the first parameter a non-const non-reference. Or you can copy construct a new vector inside the function and pass v1 to it.

    Your check of v2.at() probably won't do what you want. You probably meant to check i against v2.size().

  5. #5
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Ah! That changes eveything, doesn't it?

    take a good look at that at(). What is that you are trying to say to the compiler with it? That if at() is false it should add the vectors. Otherwise, it won't. But at() doesn't work like that. It will return the value of the element it is trying to point to. And if that element doesn't exist it will throw an exception.

    So... your concern is if V1 is bigger than V2 since being smaller or of equal size is of no consequence. To deal with that you simply take the size of V2 and test for it.

    Code:
    for(UINT i = 0; i < v1.size(); i++)
        {
          if(v2.size() > i)
            v1[i] += v2[i];
          else
            break;
        }
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  6. #6
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    I'm not that experienced in c++ so could you explain why creating operators for standard containers is not a good idea? I'd rather avoid any mishaps now than have my project blow up in my face in a few weeks.

    Oh, and I fixed the operators by getting rid of the useless at() function. Thanks a million.
    The code now works fine without that range checking. I guess I should have used it in a try catch statement but I didn't really want to look up sample code for doing that.

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    For the most part, the standard library designers have already implemented the operators that make sense for the different library classes like vector. Users of those classes know what they can expect because the behavior is the same across all standard compliant platforms. Adding an operator to the interface if it doesn't already exist can confuse users of the class.

    In addition, if you want to create an operator, it should behave in an expected and not confusing manner. For vectors, some people would think that operator+ should create a vector with all the elements in the first vector and then all the elements in the second vector (like how string's operator+ works). Your implementation is different and can be confusing. Even if you are the only one using it here, it is not a good habit to get into.

    A better alternative is simply to make a regular function. You can name this function whatever you want and comment it to make it clear what its intent is.

    Also in this case, I believe there might already exist a function that does the same thing inside the <algorithm> header, although I don't remember the name. Edit: I think you would use transform, although you have to be careful that the first vector has a larger size than the second (you would just swap them if they didn't).
    Last edited by Daved; 10-12-2006 at 09:33 PM.

  8. #8
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    Thanks for the warning. And I'll look into transform. At the moment, however, I'm trying to get the vectors to work like mathematical vectors. And it'll be for just this project, so I guess I'll chance it.

  9. #9
    Registered User
    Join Date
    Oct 2005
    Posts
    271
    Well, the stl is full of surprises!

    I've changed all my code so that it uses transform instead of my overloaded operators:
    Code:
    transform(v2.begin(), v2.end(), v1.begin() + 1, v1.begin() +1, plus<int>());
    That solves the problem of the two vectors not being equal in length as well.

    A new question. I would like to multiply a vector by a number, e.g. 0.3 * (1, 2, 3, 4) would be (0.3, 0.6, 0.9, 1.2). If that 0.3 were a constant, I wouldn't have any problem but it has to change with every iteration. So the standard invocation is:

    Code:
    void multiply(float& elem)
    {
       return elem *= 0.3;
    }
    
    ...
    
    for_each(v1.begin(), v1.end(), multiply);
    I tried changing it so that the 0.3 would actually be a variable, which the compiler just spit back out with relish:
    Code:
    void multiply(float& elem, float f_arg)
    {
       return elem *= f_arg;
    }
    
    ...
    
    for_each(v1.begin(), v2.end(), multiply(??????????)); //so how is this taken care of.
    If neither for_each nor transform is the solution, could you point me to one?

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The standard library has a predefined function object named multiplies.
    Code:
    std::transform(
        v1.begin(), v1.end(),
        v1.begin(),
        std::bind2nd(std::multiplies<float>(), 0.3f));
    std::multiplies<float>() constructs a function object for the multiplication of floats. The bind2nd() makes 0.3f the second of the two floats. The other float is then each element in the v1 vector. v1.begin() is passed as the output iterator so as to change the very range that is passed to transform().
    Last edited by laserlight; 10-13-2006 at 03:00 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Ireland
    Posts
    8,446
    Ahh... one of my favorite features of C++. And quiet a powerful one at that. Function objects and function binders. I suggest you read on those. The explanation is lenghty. But for the task at hand you can use one of those already provided under <functional>

    Code:
    #include <functional>
    for_each(v1.begin(), v1.end(), multiplies<float>(0.6))
    Last edited by Mario F.; 10-13-2006 at 03:07 AM.
    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. question about overloading operators
    By *DEAD* in forum C++ Programming
    Replies: 9
    Last Post: 05-08-2008, 10:27 AM
  2. Replies: 16
    Last Post: 10-27-2007, 12:42 PM
  3. Overloading fstream's << and >> operators
    By VirtualAce in forum C++ Programming
    Replies: 2
    Last Post: 04-09-2007, 03:17 AM
  4. operators overloading
    By waqasriazpk in forum C++ Programming
    Replies: 1
    Last Post: 07-26-2002, 01:05 AM
  5. Overloading operators...
    By Unregistered in forum C++ Programming
    Replies: 4
    Last Post: 11-21-2001, 08:24 PM