使用载体作为指标执行访问stucts的矢量(Implementing access to vecto

2019-10-23 11:41发布

一些高级语言有此功能,并且我试图用C ++实现。 我不知道是否有已经做到这一点的地方图书馆,但如果有,那就节省了我很多的麻烦。 无论如何,这里就是我试图完成:

比方说,我有一个设有一张双人床和一个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;

这些事可能吗?

Answer 1:

  1. 不能使用与现有的定义,这种语法std::vector
  2. 不能创建一个全局操作过载功能,其提供语法因为operator[]()可仅作为成员函数过载。
  3. 你可以创建一个非成员函数提供的功能,但没有使用这种语法。

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);


Answer 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';

现场演示



Answer 3:

要获得语法接近你想要的,你可以创建一个包装的结构的载体,具有成员函数为每个在结构中的成员变量的类的内容:

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();

现场演示 。



文章来源: Implementing access to vector of stucts using a vector as indices