Extracting entries at multiple indices from std::vectors in c++

Alec Jacobson

July 20, 2010

weblog/

I've been doing some C++ coding, working with matrices. In a previous project it was convenient to think of our systems in block form. This translates easily into matlab's indexing. So say you have in matlab:
a = [10,11,12,13,14,15];
Then you can extract elements 1,3,5 (remember matlab is one-indexed) by calling
b = a([1,3,5]);
which reveals
b =

    10    12    14
So in C++, I've made my first attempt at useful templating to extend the std::vector class to have this feature. It is no where near implemented the full features of matlab's operator(), but it seems to do this particular feature correctly.
#include <vector>
#include <stdio.h>

template<typename T>
class SmartVector : public std::vector<T>{
  public:
    // act like operator[]
    T operator()(size_t _Pos){
      return (*this)[_Pos];
    }
    // act like matlab operator()
    SmartVector<T> operator()(std::vector<size_t>& positions){
      SmartVector<T> sub;
      sub.resize(positions.size());
      size_t sub_i = 0;
      for(
          std::vector<size_t>::iterator pit = positions.begin();
          pit != positions.end();
          pit++,sub_i++){
        sub[sub_i] = (*this)[*pit];
      }
      return sub;
    }
};

int main(){
  // make some vector
  SmartVector<int> a;
  a.push_back(10);
  a.push_back(11);
  a.push_back(12);
  a.push_back(13);
  a.push_back(14);
  a.push_back(15);
  for(int i =0;i<a.size();i++)
    printf("a[%d] = %d\n",i,a[i]);

  // make some list of indices
  std::vector<size_t> sub_indices;
  sub_indices.push_back(0);
  sub_indices.push_back(2);
  sub_indices.push_back(4);

  // use operator() to extract entries at those indices
  SmartVector<int> b = a(sub_indices);
  printf("\nb = a([ ");
  for(int i =0;i<sub_indices.size();i++)
    printf("%d ",(int)sub_indices[i]);
  printf("]);\n\n");

  for(int i =0;i<b.size();i++)
    printf("b[%d] = %d\n",i,b[i]);
  
  return 0;
}
Then if you run ./main you should see:
a[0] = 10
a[1] = 11
a[2] = 12
a[3] = 13
a[4] = 14
a[5] = 15

b = a([ 0 2 4 ]);

b[0] = 10
b[1] = 12
b[2] = 14