C ++:通过类似成员的方法访问类成员

时间:2016-12-21 16:00:23

标签: c++ duck-typing

我有模板类,如下所示:

template<int n=3> struct Vec{
     double Values[n];
};

当然我可以直接或通过方法访问此类的元素,例如:

double& x(){
    return Values[0];
}

但如果我想制作更直观的代码:而不是

Vec<3> v;
v.x() = 5.2;

我想让用户通过以下方式完成: v.x = 5.2。它不仅是一时兴起。如果我有一个使用像struct{double x,y,z;}这样的形式的简单向量结构的现有库,我可以通过duck-typing方法创建我的模板类,以便在这种情况下有效。当然我可以(可能,我不确定)传递给这个库预定义的referenes结构 - 比如: struct{double &x=v.Values[0], &y=v.Values[1], &z=v.Values[2];}但我担心这不是实现目标的最简单方法。

啊 - 当然我可以在我的结构中添加引用类型参数,但这会导致元素大小的增加。

1 个答案:

答案 0 :(得分:4)

这是获得相同语法效果的一种方法:

template<int n=3> struct Vec{
     double Values[n];
};

template<int N> struct xyzAdapter;

template<> struct xyzAdapter<3>
{
  xyzAdapter(Vec<3>& vec) : x(vec.Values[0]), y(vec.Values[1]), z(vec.Values[2]) {}

  double& x;
  double& y;
  double& z;
};

template<int N> auto make_adapter(Vec<N>& vec) 
{
  return xyzAdapter<N>(vec);
}

int main()
{
  Vec<3> point;
  auto adapter = make_adapter(point);
  adapter.x = 6;
}

走另一条路并不是那么愉快。没有引用数组这样的东西,所以一种解决方法是使用std::reference_wrapper数组:

#include <tuple>
#include <array>
#include <functional>
#include <iostream>

template<int N = 3> struct Vector;

template<> struct Vector<3>
{
    double x, y, z;

    auto as_tuple() {
      return std::tie(x, y, z);
    }
};

template<std::size_t...Is, class Tuple>
auto as_array(std::index_sequence<Is...>, Tuple&& t)
{
  return std::array<std::reference_wrapper<double>, sizeof...(Is)> {
    std::get<Is>(t)...
  };
}

template<int N> auto as_array(Vector<N>& v)
{
  return as_array(std::make_index_sequence<N>(), v.as_tuple());
}

int main2()
{
  Vector<3> point;
  point.x = 6;

  auto arr = as_array(point);

  for (auto ref : arr) {
    std::cout << ref.get() << std::endl;
  }

  return 0;
}