将Vector3D结构传递给基于指针的API。

huangapple go评论68阅读模式
英文:

Passing Vector3D struct into pointer-based API

问题

I'm working with VTK and it's API requires all calls to be invoked either with double* or with double[3]. So the methods accept a pointer to some point in 3D space.

I've created the Vector3D struct, that is the simple aggregate:

struct Vector3D
{
    double x;
    double y;
    double z;
};

And now I want to use it for VTK API, because VTK doesnt have Point3D / Vector3D struct itself and using raw pointers is weird.
So, I've used the following method:

double* ptr() noexcept
{
    // I'm not totally sure, maybe it'd be better to use `reinterpret_cast<...>(&x)` here
    return reinterpret_cast<double*>(this);
}

And that worked, but now I realized that I need the const overload too.

const double* ptr() const noexcept
{
    return reinterpret_cast<const double*>(this);
}

But I didnt see any cases, where the reinterpret_cast<const T*> was used.
And it got me thinking: "Am I doint it right?"

英文:

I'm working with VTK and it's API requires all calls to be invoked either with double* or with double[3]. So the methods accept a pointer to some point in 3D space.

I've created the Vector3D struct, that is the simple aggregate:

struct Vector3D
{
    double x;
    double y;
    double z;
};

And now I want to use it for VTK API, because VTK doesnt have Point3D / Vector3D struct itself and using raw pointers is weird.
So, I've used the following method:

double* ptr() noexcept
{
    // I'm not totally sure, maybe it'd be better to use `reinterpret_cast<...>(&x)` here
    return reinterpret_cast<double*>(this);
}

And that worked, but now I realized that I need the const overload too.

const double* ptr() const noexcept
{
    return reinterpret_cast<const double*>(this);
}

But I didnt see any cases, where the reinterpret_cast<const T*> was used.
And it got me thinking: "Am I doint it right?"

答案1

得分: 0

是的,这没问题。如果你想要更加谨慎,你可以添加static_assert(sizeof(Vector3D) == sizeof(double) * 3);,但它可能永远不会触发。

从正式的角度来看,如果你尝试通过这个指针访问除了 x 以外的任何成员,行为是未定义的,因为+/-/[i](带有非零偏移)只能用于通过指向不同元素的指针来访问数组的元素,而你没有一个数组。

然而,在实际应用中,使用指针的代码可能隐藏在不同的翻译单元中(可能是一个库),阻止编译器注意到未定义的行为并基于此进行优化。即使在同一翻译单元中使用,编译器也不太可能破坏这样的代码。

英文:

Yes, this is fine. You can add static_assert(sizeof(Vector3D) == sizeof(double) * 3); if you want to be extra cautious, but it will probably never fire.

Formally, the behavior is undefined if you try to access any member other than x through this pointer, since +/-/[i] (with nonzero offset) can only be used to reach an element of an array through a pointer to a different element, and you don't have an array.

However, in practice, the code using the pointer is likely hidden in a different translation unit (possibly a library), preventing the compiler from noticing the UB and being able to optimize based on that. Even if used in the same translation unit, it's unlikely that a compiler would break such code.

huangapple
  • 本文由 发表于 2023年8月4日 03:57:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76831273.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定