0

So I am writing a parallel program (boost.mpi) and I want to pass pieces of a vector (as in std::vector) that can be assembled to make a whole vector.

In order to do this, I want to be able to do 2 things:

  1. grab a piece of a vector- ie say a vector has 800 elements, what is the best way to then make a subvector that contains elements 200-299 (or arbitrary indices defined by 2 int variables)?

  2. I want to create an operator that will allow me to add vectors together to create a new, longer vector. Basically, I want the same functionality that std::plus() (can concatenate strings) gives, but for vectors. I will need to be able to pass this operator as a binary operator (it would need to have the same type as std::plus()).

Any help at all with this would be much appreciated.

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Kyle
  • 217
  • 2
  • 13
  • For the first part, there's a constructor that takes ranges. Not sure if there's a better way, but `vector vSub (vMain.begin() + 200, vMain.begin() + 299);` should work. – chris Mar 30 '12 at 18:25
  • Ah, yes of course. I had forgotten about that constructor. I think that should work well. Thanks – Kyle Mar 30 '12 at 18:28

1 Answers1

0

The first part can be achieved by using the following vector constructor:

template <class InputIterator>
vector( InputIterator first, InputIterator last, 
        const Allocator& alloc = Allocator() );

The second part can be achieved using vector::insert, but there is probably a better way. I've given a sample of each below.

#include <vector>
using std::vector;

template <typename T>
vector<T> operator+ (const vector<T> &lhs, const vector<T> &rhs)
{
    vector<T> ret (lhs);
    ret.insert (ret.end(), rhs.begin(), rhs.end());
    return ret;
}

/// new //create a structure like std::plus that works for our needs, could probably turn vector into another template argument to allow for other templated classes
template <typename T>
struct Plus
{
    vector<T> operator() (const vector<T> &lhs, const vector<T> &rhs)
    {
        return lhs + rhs;
    }
};
/// end new

#include <iostream>
using std::cout;

/// new
#include <numeric>
using std::accumulate;
/// end new

template <typename T>
void print (const vector<T> &v)
{
    for (const T &i : v)
        cout << i << ' ';

    cout << '\n';
}

int main()
{
    vector<int> vMain {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; //syntax only available in C++11
    vector<int> vSub (vMain.begin() + 3, vMain.begin() + 6); //vMain[0+3]=4, vMain[0+6]=7
    vector<int> vCat = vMain + vSub;

    /// new
    vector<vector<int>> vAdd {vMain, vMain}; //create vector of vector of int holding two vMains
    /// end new

    print (vMain);
    print (vSub);
    print (vCat);

    /// new //accumulate the vectors in vAdd, calling vMain + vMain, starting with an empty vector of ints to hold the result
    vector<int> res = accumulate (vAdd.begin(), vAdd.end(), (vector<int>)(0));//, Plus<int>());
    print (res); //print accumulated result
    /// end new
}

Output:

1 2 3 4 5 6 7 8 9 10
4 5 6
1 2 3 4 5 6 7 8 9 10 4 5 6
1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10

EDIT: I really have a bad feeling about how I did this, but I've updated the code to work with things like std::accumulate.

chris
  • 60,560
  • 13
  • 143
  • 205
  • I think this should work. The only thing I need to know now is how do I pass the "+" operator as an operator? – Kyle Mar 30 '12 at 20:09
  • I've made new parts in the code stand out, but it seemed bad to be doing that way when I was writing it. You might want to see if there's something better than that. – chris Mar 30 '12 at 20:50
  • IIRC, you need to wrap `ret.end()` inside a `std::back_inserter` or UB may ensue. – moshbear Mar 30 '12 at 20:57
  • I tried, but I think it's getting stuck on the fact that `back_insert_iterator` is of type `OutputIterator`, not `InputIterator`. I'm not very experienced with the STL, so I'm not sure how to implement it. I tried `back_insert_iterator> bii = back_inserter (ret); ret.insert (bii, rhs.begin(), rhs.end());` and it couldn't find an overload. Literally putting in `ret.end()` doesn't work as it's not a container. – chris Mar 30 '12 at 21:14