某些高级语言具有此功能,我正在尝试用C ++实现。我不确定是否有一个库已经在某个地方做过,但是如果有的话,它会给我带来很多麻烦。无论如何,这就是我想要实现的目标:
假设我有一个结构的向量,它有一个double和一个int作为成员,并且我有另一个int的向量,它代表我想要保留的结构向量中元素的索引。
typedef struct
{
double x;
int y;
}s;
std::vector<s> v;
std::vector<int> inds;
是否有办法以类似于此的方式使用索引向量来实现访问结构中的元素,或者是否已在其他地方实现?
std::vector<double> dResult = v[inds].x;
std::vector<int> iResult = v[inds].y;
能够以这种方式访问所有元素也是很好的:
std::vector<double> d = v.x;
这些事情可能吗?
答案 0 :(得分:2)
std::vector
的现有定义一起使用。operator[]()
只能作为成员函数重载。
template <typename T1, typename T2>
std::vector<T2> getElements(std::vector<T1> const& vec,
std::vector<int> const& indices,
T2 (T1::*member))
{
std::vector<T2> ret;
for ( auto index : indices )
{
ret.push_back(vec[index].*member);
}
return ret;
}
然后将其用作:
std::vector<s> v;
std::vector<int> inds;
std::vector<double> dResult = getElements(v, inds, &s::x);
答案 1 :(得分:2)
不存在这样的内置功能,我也不知道任何现有的库解决方案。但是编写几个为您执行此操作的函数模板并不困难。
template<typename Container, typename T, typename M>
std::vector<M> select_mem(Container const& c, M T::* mem)
{
std::vector<M> result;
result.reserve(c.size());
std::transform(c.begin(), c.end(), std::back_inserter(result),
std::mem_fn(mem));
return result;
}
上面的模板引用了一个容器和一个指向数据成员的指针。然后,它将输入容器中每个元素的数据成员复制到输出vector
。
template<typename Container, typename Indices, typename T, typename M>
std::vector<M> select_mem(Container const& c, Indices const& ind, M T::* mem)
{
std::vector<M> result;
result.reserve(ind.size());
std::transform(ind.begin(), ind.end(), std::back_inserter(result),
[&c, mem](typename Indices::value_type const& i) {
return std::mem_fn(mem)(c[i]);
});
return result;
}
这是前一个模板的扩展,它也接受一个索引容器,只复制输入容器中指定索引处的数据成员。
按如下方式使用它们:
std::vector<s> v {{10, 1}, {20, 2}, {30, 3}, {40, 4}};
for(auto const& x : select_mem(v, &s::x)) {
std::cout << x << ' ';
}
std::cout << '\n';
std::vector<int> indices{1,2};
for(auto const& x : select_mem(v, indices, &s::x)) {
std::cout << x << ' ';
}
std::cout << '\n';
答案 2 :(得分:0)
要使语法接近您想要的语法,您可以创建一个包装结构向量的类,并为结构中的每个成员变量提供成员函数:
class VecS {
const std::vector<s>& v;
const std::vector<int>* inds;
template<typename R>
std::vector<R> impl(R s::* pm) const {
if (inds) {
std::vector<R> ret(inds->size());
auto get_at_index = [this, pm](int index){ return v[index].*pm; };
std::transform(inds->begin(), inds->end(), ret.begin(), get_at_index);
return ret;
}
std::vector<R> ret(v.size());
std::transform(v.begin(), v.end(), ret.begin(), std::mem_fn(pm));
return ret;
}
public:
VecS(const std::vector<s>& v) : v(v), inds(nullptr) {}
VecS(const std::vector<s>& v, const std::vector<int>& inds) : v(v), inds(&inds) {}
std::vector<double> x() const { return impl(&s::x); }
std::vector<int> y() const { return impl(&s::y); }
};
如果您愿意滥用operator[]
,您可以更进一步,添加以下内容:
VecS operator[](const std::vector<int>& inds) { return VecS(v, inds); }
然后你可以写:
auto vs = VecS(v);
auto dResult = vs[inds].x();
auto iResult = vs[inds].y();
当然:
auto d = vs.x();