我有一个Visual Studio 2008 C ++项目,我希望将该结构类型的向量的一个struct元素复制到一个新向量。例如:
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 );
}
有比这更好/更优雅的方式吗?
谢谢, PaulH
答案 0 :(得分:18)
在Visual C ++ 2008中,不,这就像它所获得的那样“优雅”。标准库提供了可用于操作容器的算法,但在大多数情况下 - 特别是在像这样的简单用例中 - 它们使用起来太麻烦了。
C ++ 11将lambda表达式添加到C ++中。 Visual C ++ 2010和其他C ++编译器的最新版本支持此C ++ 11功能。使用lambda表达式,您可以轻松地将transform
算法用于您的任务:
std::transform(v1.begin(), v1.end(), std::back_inserter(v2),
[](Foo const& x) { return x.b; });
如果没有lambda表达式,则必须定义一个函数来从结构中提取b
元素:
long get_b(Foo const& x) { return x.b; }
然后,您可以将此函数与transform
算法一起使用:
std::transform(v1.begin(), v1.end(), std::back_inserter(v2), get_b);
但是,对于这样的简单用例,这很快就会导致代码难以处理,因为很难将所有相关功能整齐地保存在一起。
答案 1 :(得分:1)
这实际上取决于你对“更好”的意思。
如果你的意思是如果使用模板技巧可以写同样的话,那么答案是肯定的:
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));
在我看来,这比显式循环更糟糕,但其优点是成员指针(即您正在复制的结构的哪一部分)可以是运行时参数。
如果您需要复制的成员是已知并修复的,那么我会说显式循环是最好的方法(我几乎无法想象使用类似模板的情况,其中成员指针是模板参数使任何意义上的。)