I have a Visual Studio 2008 C++ project where I would like to copy one struct element of a vector of that struct type to a new vector. For example:
struct Foo {
int a;
long b;
};
std::vector< Foo > v1;
std::vector< long > v2;
for( std::vector< Foo >::const_iterator it = v1.begin(); it != v1.end(); ++it )
{
v2.push_back( it->b );
}
Is there a better/more elegant way than this?
Thanks, PaulH
In Visual C++ 2008, no, this is about as "elegant" as it gets. The Standard Library provides algorithms that can be used to manipulate containers, but in most scenarios--especially in simple use cases like this one--they are far too cumbersome to use.
C++11 adds lambda expressions to C++. Visual C++ 2010 and recent versions of other C++ compilers support this C++11 feature. With lambda expressions, you can easily use the transform
algorithm for your task:
std::transform(v1.begin(), v1.end(), std::back_inserter(v2),
[](Foo const& x) { return x.b; });
Without lambda expressions, you'd have to define a function to extract the b
element from the struct:
long get_b(Foo const& x) { return x.b; }
You could then use this function with the transform
algorithm:
std::transform(v1.begin(), v1.end(), std::back_inserter(v2), get_b);
However, for simple use cases like this, this can quickly lead to unwieldy code as it is difficult to neatly keep all of the related functions together.
It really depends on what you mean with "better".
If you mean if the same can be written by using template trickery then the answer is yes:
template<typename C, typename T>
struct MemberGetter
{
T C::*mp;
MemberGetter(T C::*mp) : mp(mp) { }
T operator()(const C& c) { return c.*mp; }
};
struct Foo
{
double dm;
};
...
std::vector<double> x;
std::vector<Foo> y;
std::transform(y.begin(), y.end(),
std::back_inserter(x),
MemberGetter<Foo, double>(&Foo::dm));
This is in my opinion worse than an explicit loop, but has the advantage that the member pointer (i.e. which part of the structure you are copying) can be a runtime parameter.
If the member you need to copy is instead known and fixed then I'd say that the explicit loop is the best way (I can barely imagine corner cases in which using a similar template where the member pointer is a template parameter makes any sense).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With