C++ 在结构中重载 operator()
C++ overloading operator() in struct
这是来自 Box2d 物理引擎的 b2Math.h 的代码。
struct b2Vec2
{ ...
/// Read from and indexed element.
float operator () (int i) const
{
return (&x)[i];
}
/// Write to an indexed element.
float operator () (int i)
{
return (&x)[i];
}
...
float x, y;
}
为什么我们不能只使用 SomeVector.x 和 SomeVector.y 到 read/write 矢量坐标? return (&x)[i];
行实际上是如何工作的?我的意思是,对结构的 x 组件的引用之后的数组括号 [] 对我来说并不清楚。
预先感谢您的回复。
Here is a code from b2Math.h from Box2d physics engine.
您发布的 Box2D 源代码的复制和粘贴似乎有错误。特别是,非常量方法中似乎缺少一个符号。
此外,此代码片段似乎来自当前 2.3.2 发布代码以外的代码库。
这是来自 Box2D 2.3.2 sources on GitHub 的部分:
/// Read from and indexed element.
float32 operator () (int32 i) const
{
return (&x)[i];
}
/// Write to an indexed element.
float32& operator () (int32 i)
{
return (&x)[i];
}
Why can't we just use SomeVector.x and SomeVector.y to read/write vector coordinates?
我们可以,而且我们通常会这样做。
然而,在 Box2D 中有一些代码(特别是 b2AABB::RayCast
)似乎是从一个算法(b2AABB::RayCast
的注释说 "From Real-time Collision Detection, p179")编写的,它迭代 x 和y 作为数组下标零和一。我猜 Erin Cato(Box2D 的作者)以这种方式实现了这些运算符:(a) 使访问在风格上更符合算法,(b) 使其工作,以及 (c) 使其在看起来有效的方式。我可以确认它至少有效。
我在 my own fork of Box2D 中重写了这些运算符。我将其接口更改为使用 []
(而不是 ()
),并将其实现更改为使用 switch
语句来显式访问 x
或 y
。我所做的后者显然是为了避免潜在的未定义行为 w.r.t。 C++ 标准。
这里是我的实现的相关部分的 片段(请注意,我并不声称这是完美的或好,只是它是一个有效的替代实现并且它应该明确依赖于定义的行为):
/// Accesses element by index.
/// @param i Index (0 for x, 1 for y).
auto operator[] (size_type i) const
{
assert(i < max_size());
switch (i)
{
case 0: return x;
case 1: return y;
default: break;
}
return x;
}
/// Accesses element by index.
/// @param i Index (0 for x, 1 for y).
auto& operator[] (size_type i)
{
assert(i < max_size());
switch (i)
{
case 0: return x;
case 1: return y;
default: break;
}
return x;
}
And how actually line return (&x)[i]; works?
正如我上面所暗示的,我之前已经研究过这个确切的问题。
当结构的 x 和 y 成员变量的内存布局与具有两个浮点数的数组相同时有效;它通常会这样做。因此,符号 (&
) 获取 x
参数的地址,然后将该地址视为数组开头的地址,然后按 i
.[=27= 索引]
不过,就 C++ 标准而言,我不认为这是已定义的行为。然而,它的定义不够明确,不符合我的口味。
希望这能回答您的问题。
这是来自 Box2d 物理引擎的 b2Math.h 的代码。
struct b2Vec2
{ ...
/// Read from and indexed element.
float operator () (int i) const
{
return (&x)[i];
}
/// Write to an indexed element.
float operator () (int i)
{
return (&x)[i];
}
...
float x, y;
}
为什么我们不能只使用 SomeVector.x 和 SomeVector.y 到 read/write 矢量坐标? return (&x)[i];
行实际上是如何工作的?我的意思是,对结构的 x 组件的引用之后的数组括号 [] 对我来说并不清楚。
预先感谢您的回复。
Here is a code from b2Math.h from Box2d physics engine.
您发布的 Box2D 源代码的复制和粘贴似乎有错误。特别是,非常量方法中似乎缺少一个符号。
此外,此代码片段似乎来自当前 2.3.2 发布代码以外的代码库。
这是来自 Box2D 2.3.2 sources on GitHub 的部分:
/// Read from and indexed element.
float32 operator () (int32 i) const
{
return (&x)[i];
}
/// Write to an indexed element.
float32& operator () (int32 i)
{
return (&x)[i];
}
Why can't we just use SomeVector.x and SomeVector.y to read/write vector coordinates?
我们可以,而且我们通常会这样做。
然而,在 Box2D 中有一些代码(特别是 b2AABB::RayCast
)似乎是从一个算法(b2AABB::RayCast
的注释说 "From Real-time Collision Detection, p179")编写的,它迭代 x 和y 作为数组下标零和一。我猜 Erin Cato(Box2D 的作者)以这种方式实现了这些运算符:(a) 使访问在风格上更符合算法,(b) 使其工作,以及 (c) 使其在看起来有效的方式。我可以确认它至少有效。
我在 my own fork of Box2D 中重写了这些运算符。我将其接口更改为使用 []
(而不是 ()
),并将其实现更改为使用 switch
语句来显式访问 x
或 y
。我所做的后者显然是为了避免潜在的未定义行为 w.r.t。 C++ 标准。
这里是我的实现的相关部分的 片段(请注意,我并不声称这是完美的或好,只是它是一个有效的替代实现并且它应该明确依赖于定义的行为):
/// Accesses element by index.
/// @param i Index (0 for x, 1 for y).
auto operator[] (size_type i) const
{
assert(i < max_size());
switch (i)
{
case 0: return x;
case 1: return y;
default: break;
}
return x;
}
/// Accesses element by index.
/// @param i Index (0 for x, 1 for y).
auto& operator[] (size_type i)
{
assert(i < max_size());
switch (i)
{
case 0: return x;
case 1: return y;
default: break;
}
return x;
}
And how actually line return (&x)[i]; works?
正如我上面所暗示的,我之前已经研究过这个确切的问题。
当结构的 x 和 y 成员变量的内存布局与具有两个浮点数的数组相同时有效;它通常会这样做。因此,符号 (&
) 获取 x
参数的地址,然后将该地址视为数组开头的地址,然后按 i
.[=27= 索引]
不过,就 C++ 标准而言,我不认为这是已定义的行为。然而,它的定义不够明确,不符合我的口味。
希望这能回答您的问题。