我有模板类,如下所示:
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];}
但我担心这不是实现目标的最简单方法。
啊 - 当然我可以在我的结构中添加引用类型参数,但这会导致元素大小的增加。
答案 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;
}