Hra*_*yan 5 c++ struct field accessor
假设我有一个结构
struct Vector3 {
float x;
float y;
float z;
};
Run Code Online (Sandbox Code Playgroud)
注意sizeof(Vector3)
必须保持不变。
编辑:我对没有二传手的解决方案感兴趣。
不要让我们创建该 struct 的实例Vector3 pos
。我如何能实现我的结构,所以我可以有这样的事情pos.xy = 10 // updates x and y
还是pos.yz = 20 // updates y and z
和pos.xz = 30 // updates x and z
?
由于您的类型是标准布局,因此我认为按照 C++ 标准执行此操作的唯一合法union
方法是使用包含具有自定义定义的子对象的a operator=
。
使用union
,您可以查看活动成员的通用首字母序列,前提是所有类型都是标准布局类型。因此,如果我们精心制作一个共享相同公共成员的对象(例如,float
顺序相同的 3 个对象),那么我们可以在它们之间“混合”,而不会违反严格别名。
为了实现这一点,我们需要创建一堆成员,这些成员都具有相同顺序、标准布局类型的相同数据。
作为一个简单的示例,让我们创建一个基本的代理类型:
template <int...Idx>
class Vector3Proxy
{
public:
// ...
template <int...UIdx,
typename = std::enable_if_t<(sizeof...(Idx)==sizeof...(UIdx))>>
auto operator=(const Vector3Proxy<UIdx...>& other) -> Vector3Proxy&
{
((m_data[Idx] = other.m_data[UIdx]),...);
return (*this);
}
auto operator=(float x) -> Vector3Proxy&
{
((m_data[Idx] = x),...);
return (*this);
}
// ...
private:
float m_data[3];
template <int...> friend class Vector3Proxy;
};
Run Code Online (Sandbox Code Playgroud)
在此示例中,并未使用 的所有成员m_data
- 但它们的存在是为了满足“公共初始序列”要求,这将允许我们通过union
.
这可以根据您的需要进行构建;float
单组件运算符的转换、算术支持等。
使用这样的类型,我们现在可以Vector3
从这些代理类型构建对象
struct Vector3
{
union {
float _storage[3]; // for easy initialization
Vector3Proxy<0> x;
Vector3Proxy<1> y;
Vector3Proxy<2> z;
Vector3Proxy<0,1> xy;
Vector3Proxy<1,2> yz;
Vector3Proxy<0,2> xz;
// ...
};
};
Run Code Online (Sandbox Code Playgroud)
然后可以轻松地使用该类型一次分配多个值:
Vector3 x = {1,2,3};
x.xy = 5;
Run Code Online (Sandbox Code Playgroud)
或者将一个零件的组件分配给另一零件:
Vector3 a = {1,2,3};
Vector3 b = {4,5,6};
a.xy = b.yz; // produces {5,6,3}
Run Code Online (Sandbox Code Playgroud)
该解决方案还确保sizeof(Vector3)
不会改变,因为所有代理对象的大小相同。
注意:union
在 C++ 中,将 a与匿名s 一起使用是无效的struct
,尽管某些编译器支持它。因此,尽管将其重写为:
union {
struct {
float x;
float y;
float z;
}; // invalid, since this is anonymous
struct {
...
} xy;
}
Run Code Online (Sandbox Code Playgroud)
这在标准 C++ 中无效,并且不是可移植的解决方案。
归档时间: |
|
查看次数: |
239 次 |
最近记录: |