invisiblerhino
invisiblerhino

Reputation: 869

Getting vectors of members from vectors of objects

I have the following setup

class obj {
  public:
  int a();
  int b();
  int c();
  int d();
};

std::vector<obj> obj_vector;
//Fill obj_vector

and I would like to access the methods (this is for an interface that expects vectors of ints, individually).

void func(vector<int>a ,vector<int> b,vector<int> c,vector<int> d);

I thought initially that extending the vector was the best approach, but have been warned against it.

I've implemented

get_a_vec(vector<obj>);

etc but this is a bit clumsy. Are there any nice alternatives?

Thanks in advance!

Upvotes: 0

Views: 100

Answers (3)

Tamer Shlash
Tamer Shlash

Reputation: 9523

What I understood is that you want a function that extracts the values of a from your objs in a given vector and puts them in another vector, if this is true, then I suggest using a friend function.

Declaring a friend function in the class obj allows this function to access private data members of that class.

class obj {
    friend vector<int> get_a_vec(const vector<obj>&);
    friend vector<int> get_b_vec(const vector<obj>&);
    friend vector<int> get_c_vec(const vector<obj>&);
    friend vector<int> get_d_vec(const vector<obj>&);     
    int a;
    int b;
    int c;
    int d;
};

vector<int> get_a_vec(const vector<obj>& vec)
{
    vector<int> result(vec.size());
    for (unsigned i = 0;i<vec.size();i++)
        result->at(i) = vec[i].a;
    return result;
}

Upvotes: 0

Stack Overflow is garbage
Stack Overflow is garbage

Reputation: 248269

Write a function which retrieves the desired member from a single object.

Then pass that function to std::transform.

If you have a int get_a_member(obj&) function, for example, simply call

std::vector<int> avec;
std::transform(obj_vector.begin(), obj_vector.end(), get_a_member);

If you want a more complex or reusable function, make it a functor instead. Then you can pass parameters to it in its constructor (for example telling it which member to return).

Upvotes: 2

Mike Seymour
Mike Seymour

Reputation: 254751

You could write a generic function to extract any class member from a sequence of objects:

template <typename InIt, typename OutIt, typename Class, typename Member>
void extract(InIt start, InIt end, OutIt out, Member Class::*member) {
    for (; start != end; ++start, ++out) {
        *out = (*start).*member;
    }
}

// Example
int main()
{
    std::vector<obj> objs {{1,2,3,4},{5,6,7,8}};
    std::vector<int> ints;

    extract(objs.begin(), objs.end(), back_inserter(ints), &obj::a);

    std::copy(ints.begin(), ints.end(), 
              std::ostream_iterator<int>(std::cout, "\n"));
}

Upvotes: 1

Related Questions